2.常用的离散化方法
常用的离散化方法有等宽法、等频法和(一维)聚类。
(1)等宽法
将属性的值域分成具有相同宽度的区间,区间的个数由数据本身的特点决定,或者由用户指定,类似于制作频率分布表。
(2)等频法
将相同数量的记录放进每个区间。
这两种方法简单,易于操作,但都需要人为地规定划分区间的个数。同时,等宽法的缺点在于它对离群点比较敏感,倾向于不均匀地把属性值分布到各个区间。有些区间包含许多数据,而另外一些区间的数据极少,这样会严重损坏建立的决策模型。等频法虽然避免了上述问题的产生,却可能将相同的数据值分到不同的区间以满足每个区间中固定的数据个数。
(3)基于聚类分析的方法
一维聚类的方法包括两个步骤,首先将连续属性的值用聚类算法(如K-Means算法)进行聚类,然后再将聚类得到的簇进行处理,合并到一个簇的连续属性值并做同一标记。聚类分析的离散化方法也需要用户指定簇的个数,从而决定产生的区间数。
下面使用上述3种离散化方法对“医学中中医证型的相关数据”进行连续属性离散化的对比,该属性的示例数据见表4-4。
表4-4 中医证型连续属性离散化数据
数据详见:demo/data/discretization_data.xls
具体可以参考第8章中相关章节,其Python代码如代码清单4-3所示。
代码清单4-3 数据离散化
#-*- coding: utf-8 -*- #数据规范化 import pandas as pd datafile = '../data/discretization_data.xls' #参数初始化 data = pd.read_excel(datafile) #读取数据 data = data[u'肝气郁结证型系数'].copy() k = 4 d1 = pd.cut(data, k, labels = range(k)) #等宽离散化,各个类比依次命名为0,1,2,3 #等频率离散化 w = [1.0*i/k for i in range(k+1)] w = data.describe(percentiles = w)[4:4+k+1] #使用describe函数自动计算分位数 w[0] = w[0]*(1-1e-10) d2 = pd.cut(data, w, labels = range(k)) from sklearn.cluster import KMeans #引入KMeans kmodel = KMeans(n_clusters = k, n_jobs = 4) #建立模型,n_jobs是并行数,一般等于CPU数较好 kmodel.fit(data.reshape((len(data), 1))) #训练模型 c = pd.DataFrame(kmodel.cluster_centers_).sort(0) #输出聚类中心,并且排序(默认是随机 序的) w = pd.rolling_mean(c, 2).iloc[1:] #相邻两项求中点,作为边界点 w = [0] + list(w[0]) + [data.max()] #把首末边界点加上 d3 = pd.cut(data, w, labels = range(k)) def cluster_plot(d, k): #自定义作图函数来显示聚类结果 import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号 plt.figure(figsize = (8, 3)) for j in range(0, k): plt.plot(data[d==j], [j for i in d[d==j]], 'o') plt.ylim(-0.5, k-0.5) return plt cluster_plot(d1, k).show() cluster_plot(d2, k).show() cluster_plot(d3, k).show()
代码详见:demo/code/data_discretization.m
运行上面的程序,可以得到图4-2~图4-4所示的结果。
图4-2 等宽离散化结果
图4-3 等频离散化方法
图4-4 (一维)聚类离散化方法
分别用等宽法、等频法和(一维)聚类对数据进行离散化,将数据分成4类,然后将每一类记为同一个标识,如分别记为A1、A2、A3、A4,再进行建模。
4.3.4 属性构造
在数据挖掘的过程中,为了提取更有用的信息,挖掘更深层次的模式,提高挖掘结果的精度,我们需要利用已有的属性集构造出新的属性,并加入到现有的属性集合中。
比如,进行防窃漏电诊断建模时,已有的属性包括供入电量、供出电量(线路上各大用户用电量之和)。理论上供入电量和供出电量应该是相等的,但是由于在传输过程中存在电能损耗,使得供入电量略大于供出电量,如果该条线路上的一个或多个大用户存在窃漏电行为,会使得供入电量明显大于供出电量(详见线户关系图6-7)。反过来,为了判断是否有大用户存在窃漏电行为,可以构造出一个新的指标——线损率,该过程就是构造属性。新构造的属性线损率按如下公式计算。
线损率的正常范围一般在3%~15%,如果远远超过该范围,就可以认为该条线路的大用户很可能存在窃漏电等用电异常行为。
根据线损率的计算公式,由供入电量、供出电量进行线损率的属性构造代码,如代码清单4-4所示。
代码清单4-4 线损率属性构造
#-*- coding: utf-8 -*- #线损率属性构造 import pandas as pd #参数初始化 inputfile= '../data/electricity_data.xls' #供入供出电量数据 outputfile = '../tmp/electricity_data.xls' #属性构造后数据文件 data = pd.read_excel(inputfile) #读入数据 data[u'线损率'] = (data[u'供入电量'] - data[u'供出电量'])/data[u'供入电量'] data.to_excel(outputfile, index = False) #保存结果
代码详见:demo/code/line_rate_construct.py
4.3.5 小波变换
小波变换[4][5]是一种新型的数据分析工具,是近年来兴起的信号分析手段。小波分析的理论和方法在信号处理、图像处理、语音处理、模式识别、量子物理等领域得到越来越广泛的应用,它被认为是近年来在工具及方法上的重大突破。小波变换具有多分辨率的特点,在时域和频域都具有表征信号局部特征的能力,通过伸缩和平移等运算过程对信号进行多尺度聚焦分析,提供了一种非平稳信号的时频分析手段,可以由粗及细地逐步观察信号,从中提取有用信息。
能够刻画某个问题的特征量往往是隐含在一个信号中的某个或者某些分量中,小波变换可以把非平稳信号分解为表达不同层次、不同频带信息的数据序列,即小波系数。选取适当的小波系数,即完成了信号的特征提取。下面将介绍基于小波变换的信号特征提取方法。
(1)基于小波变换的特征提取方法
基于小波变换的特征提取方法主要有:基于小波变换的多尺度空间能量分布特征提取、基于小波变换的多尺度空间的模极大值特征提取、基于小波包变换的特征提取、基于适应性小波神经网络的特征提取,详见表4-5。
表4-5 基于小波变换的特征提取方法
(2)小波基函数
小波基函数是一种具有局部支集的函数,并且平均值为0,小波基函数满足ψ(0)=∫ψ(t)dt=0。常用的小波基有Haar小波基、db系列小波基等。Haar小波基函数如图4-5所示。
图4-5 Haar小波基函数
(3)小波变换
对小波基函数进行伸缩和平移变换:
其中,a为伸缩因子,b为平移因子。
任意函数f(t)的连续小波变换(CWT)为:
可知,连续小波变换为f(t)→Wf(a,b)的映射,对小波基函数ψ(t)增加约束条件Cψ=,就可以由Wf(a,b)逆变换得到f(t)。其中为ψ(t)的傅里叶变换。
其逆变换为:
下面介绍基于小波变换的多尺度空间能量分布特征提取方法。
(4)基于小波变换的多尺度空间能量分布特征提取方法
应用小波分析技术可以把信号在各频率波段中的特征提取出来,基于小波变换的多尺度空间能量分布特征提取方法是对信号进行频带分析,再分别以计算所得的各个频带的能量作为特征向量。
信号f(t)的二进小波分解可表示为:
其中A是近似信号,为低频部分;D是细节信号,为高频部分,此时信号的频带分布如图4-6所示。
图4-6 多尺度分解的信号频带分布
信号的总能量为:
选择第j层的近似信号和各层的细节信号的能量作为特征,构造特征向量:
利用小波变换可以对声波信号进行特征提取,提取出可以代表声波信号的向量数据,即完成从声波信号到特征向量数据的变换。本例利用小波函数对声波信号数据进行分解,得到5个层次的小波系数。利用这些小波系数求得各个能量值,这些能量值即可作为声波信号的特征数据。
在Python中,Scipy本身提供了一些信号处理函数,但不够全面,而更好的信号处理库是PyWavelets(pywt)。PyWavelets完成上述任务,程序实现如代码清单4-5所示。
代码清单4-5 小波变换特征提取代码
#-*- coding: utf-8 -*- #利用小波分析进行特征分析 #参数初始化 inputfile= '../data/leleccum.mat' #提取自Matlab的信号文件 from scipy.io import loadmat #mat是Python专用格式,需要用loadmat读取它 mat = loadmat(inputfile) signal = mat['leleccum'][0] import pywt #导入PyWavelets coeffs = pywt.wavedec(signal, 'bior3.7', level = 5) #返回结果为level+1个数字,第一个数组为逼近系数数组,后面的依次是细节系数数组
代码详见:demo/code/wave_analyze.py
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论