特征工程是机器学习中非常重要的一个环节,它的好坏直接影响了机器学习效果的优劣。而特征工程里非常关键的一步就是特征选择。
如果把机器学习比作是一个厨师做菜的过程,那么数据就是原材料(菜),模型可以理解为炒菜的方式(蒸、煮、炒、炖等等),算法就是这个厨师的炒菜水平。特征工程就是前期处理食材的过程,有了食材(数据),首先要看看食材是啥,长什么样(源数据分布情况),然后看看食材是否新鲜,是否有磕碰破损(数据是否有缺失),再然后就是选取适当的部分(比如我炒做鸡蛋,鸡蛋壳肯定不能一起炒吧)完成我们想做的菜。
11.1 子集搜索与评价
对象都有很多属性来描述,属性也称为特征(feature),用于刻画对象的某一个特性。对一个学习任务而言,有些属性是关键有用的,而有些属性则可能不必要纳入训练数据。对当前学习任务有用的属性称为相关特征(relevant feature)、无用的属性称为无关特征(irrelevantfeature)。从给定的特征集合中选择出相关特征子集的过程,称为特征选择(feature selection)。
特征选择时一个数据预处理(data preprocessing)过程,在现实机器学习任务中,基于避免维数灾难和降低不相关特征带来的学习难度,在获得数据之后往往会先进行特征选择再训练学习器。当然特征选择要确保不丢失重要特征。给定数据集,若学习任务不同,则相关特征很可能不同,因此无关特征是指与当前学习任务无关。若一个属性是从其他属性中推演而出的,则成为冗余特征(redundant feature)。
假定数据中不涉及冗余特征,并假定初始的特征集包含了所有的重要信息,那么如何进行特征选择呢?要从初始的特征集合中选取一个包含了所有重要信息的特征子集,若没有任何领域知识作为先验假设,那就只有遍历所有子集,这计算开销相当大,一旦属性稍多就会出现组合爆炸。较为可行的一个做法是:先产生一个候选子集,然后评价,基于评价结果产生下一轮候选子集,再评价…如此下去,直至无法找到更好的候选子集。这个做法就关系两个很重要的过程:如何评价候选子集的优劣?又如何根据评价结果遴选下一轮候选子集呢?
1)子集搜索(subsetsearch)
给定特征集合{a1,a2,…,ad},可将每个特征看做一个候选子集,对这d个候选单特征子集进行评价,选出一个最优的,然后加入一个特征,构成包含两个特征的候选子集…假定在k+1轮时,最后的候选(k+1)个特征子集不如上一轮的选定集,则停止生成候选子集,并将上一轮选定的k特征集合作为特征选择结果。上述这种逐渐增加相关特征的策略称为前向(forward)搜索。如果从完整的特征集合开始,每次尝试去掉一个无关特征,这样逐渐减少特征的策略称为后向(backward)搜索。也可将前后和后向搜索结合起来,每一轮逐渐增加选定相关特征、同时减少无关特征,这样的策略称为双向(bidirectional)搜索。
上述策略是贪心的,因为它们仅仅考虑了使本轮选定集最优,如在第三轮假定a5优于a6,于是选定集为{a2,a4,a5},然后在第四轮却可能是{a2,a4,a6,a8}优于所有的{a2,a4,a5,ai}。要解决这个问题,就只能进行穷举搜索。
2)子集评价(subsetevaluation)
给定数据集D,假定D中第i类样本所占的比例为pi(i=1,2,…,|y|),假定样本属性均为离散型。对属性子集A,假定根据其取值将D分成了V个子集{D1,D2,…,DV},每个子集中的样本在A上取值相同,计算属性子集A的信息增益:
信息增益Gain(A)越大,意味着特征子集A包含的欧主语分类的信息越多。如此,对每个候选特征子集,可基于训练数据集D来计算其信息增益,以此作为评价准则。
更一般的,特征子集A实际上确定了对数据集D的一个划分,每个划分区域对应着A上的一个取值,而样本标记信息y则对应对D的真实划分,通过估算这两个划分的差异,就能对A进行评价。与y对应的划分的差异越小,则说明A越好。信息熵仅是判断这个差异的一个途径,其他能判断两个划分差异的机制都能用于特征子集评价。
综上两点,将特征子集搜索机制与子集评价机制结合,就可得到特征选择方法。如将前向搜索与信息熵结合,与决策树相似。事实上,决策树也可用于特征选择,树节点的划分属性所组成的集合就是选择出的特征子集。其他的特征选择方法未必如决策树般特征选择这么明显,不过在本质上都显式或隐式地结合了某种或多种子集搜索机制和子集评价机制。
常见的特征选择方法大致可分三类:过滤式(filter)、包裹式(wrapper)和嵌入式(embedding)。
11.2 过滤式选择
过滤式方法先对数据集进行特征选择,然后再训练学习器,特征选择过程与后续学习器无关。
这相当于先用特征选择过程对初始特征进行“”过滤“,再用过滤的特征来训练模型。
Relief是一种著名的过滤式特征选择方法,该方法设计了一个相关统计量来度量特征的重要性。该统计量是一个向量,其每个分量对应于一个初始特征,而特征子集的重要性则是由子集中每个特征所对应的相关统计量分量之和决定。指定一个阈值,选择比阈值大的相关统计量分量所对应的特征即可;也可指定要选择的特征个数k,然后选择相关统计量分量最大的k个特征。
Relief的关键是如何确定相关统计量。给定训练集{(x1,y1),(x2,y2),…,(xm,ym)},对每个示例xi,Relief先在xi的同类样本中寻找其最近邻xi,nh,称为猜中近邻(near-hit);再从xi的异类样本中寻找其最近邻xi,nm,称为猜错近邻(near-miss);相关统计量对应于属性j的分量为:
11.3包裹式选择
和过滤式特征选择不考虑后续学习器不同,包裹式特征选择直接把最终将要使用的学习器性能作为特征子集的评价准则。换言之,包裹式特征选择的目的就是为给定学习器选择最有利于其性能、量身定做的特征子集。一般而言,包裹式特征选择方法直接针对给定学习器进行优化,从最终学习器性能来说,包裹式特征选择比过滤式特征选择更好,但由于在特征选择过程中要多次训练学习器,其计算开销也比过滤式特征选大很多。
LVW(LasVegas Wrapper)是一个典型的包裹式特征选择方法,它在拉斯维加斯方法框架下随用随机策略进行子集搜索,并以最终分类器的误差为特征子集评价准则。算法描述如下:
输入:数据集D;
特征集A;
学习算法Σ;
停止条件控制参数T。
过程:
E=∞;//初始误差无穷大
D=|A|;
A*=A;
t=0;
while t
输出:特征子集A*
算法中通过在数据集D上使用交叉验证法CrossValidation来估计学习器Σ的误差,这个误差是在仅考虑特征子集A’时得到的,即特征子集A’上的误差,若它比当前特征子集A上的误差更小,或者误差相当但A’中包含的特征数更少,则将A’保留下来。
由于LVW算法中特征子集搜索采用了随机策略,而每次特征子集评价都需训练学习器,计算开销很大,因此算法设置了停止条件控制参数T。然而,整个LVW算法是基于拉斯维加斯方法框架,若初始特征数很多(即|A|很大)、T设置较大,则算法可能运行很长时间都打不到停止条件。就是,若有时间限制,可能无解。
注意:拉斯维加斯方法和蒙特卡罗方法是两个以著名赌城名字命名的随机化方法。两者主要区别是:若有时间限制,则拉斯维加斯方法或者给出满足要求的解,或者不给出解;而蒙特卡罗方法一定会给出解,虽然给出的解未必满足要求。若无时间限制,则两者都能给出满足要求的解。
11.4 嵌入式选择与L1正则化
在过滤式和包裹式特征选择方法中,特征选择过程与学习器训练过程有明显的分别;
与此不同,嵌入式特征选择是将特征选择过程与学习器训练过程融为一体,两者在同一个优化过程中完成,即在学习器训练过程中自动地进行了特征选择。
用特征子集评价与学习器训练的前后关系来来说,过滤式是在学习器训练前完成特征子集选择和评价;
包裹式是在学习器训练后评价特征子集从而选择特征;嵌入式则是在学习器训练过程中同步评价并选择特征子集。
过滤式选择和包裹式选择和模型优化的过程是分开的,而嵌入式顾名思义是和模型优化过程合在一起的。
以线性模型为例,损失函数为平方损失,则目标函数为:
但是,当特征数量远远超过样本数量的时候,训练出来的模型就会出现过拟合,为了避免这种情况,我们就需要加入正则项, 引入L-p范数,p=0,1,2等任意非负数
其中 λ>0\lambda>0λ>0 是正则化参数,当p=2时,上式称为“岭回归”,当p=1时,称为“LASSO”回归,这两中正则化方式都可以方式过拟合,但是在本质上有差异,L2范数通过调整每个特征的权重来避免过拟合,而L1范数则是会对特征进行筛选,留下有效的特征,删除无效的特征。
L2范数可以直接求导解决,但是L1范数不能,只能通过求次微分来计算,周志华老师《机器学习》书里提到用近似梯度下降(PGD)来求解。求解过程不在此具体展开。
11.5 稀疏表示与字典学习
1.什么是稀疏表示:
假设我们用一个M*N的矩阵表示数据集X,每一行代表一个样本,每一列代表样本的一个属性,一般而言,该矩阵是稠密的,即大多数元素不为0。 稀疏表示的含义是,寻找一个系数矩阵A(K*N)以及一个字典矩阵B(M*K),使得B*A尽可能的还原X,且A尽可能的稀疏。A便是X的稀疏表示。
2.字典学习:
该算法理论包含两个阶段:字典构建阶段(Dictionary Generate)和利用字典(稀疏的)表示样本阶段(Sparse coding with a precomputed dictionary)。这两个阶段(如下图)的每个阶段都有许多不同算法可供选择,每种算法的诞生时间都不一样,以至于稀疏字典学习的理论提出者已变得不可考。笔者尝试找了Wikipedia和Google Scolar都无法找到这一系列理论的最早发起人。
11.6 压缩感知
压缩感知简介
实验
要利用python实现,电脑必须安装以下程序
python (本文用的python版本为3.6)
numpy python包(本文用的版本为1.10.4)
scipy python包(本文用的版本为0.17.0)
pillow python包(本文用的版本为3.1.1)
另外需要下载lena图片放在和程序同一个目录下面
#coding:utf-8
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# DCT基作为稀疏基,重建算法为OMP算法 ,图像按列进行处理
# 参考文献: 任晓馨. 压缩感知贪婪匹配追踪类重建算法研究[D].
#北京交通大学, 2012.
#
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# 导入所需的第三方库文件
import numpy as np
import math
from PIL import Image
#读取图像,并变成numpy类型的 array
im = np.array(Image.open('lena.bmp')) #图片大小256*256
#生成高斯随机测量矩阵
sampleRate=0.7 #采样率
Phi=np.random.randn(256*sampleRate,256)
#生成稀疏基DCT矩阵
mat_dct_1d=np.zeros((256,256))
v=range(256)
for k in range(0,256):
dct_1d=np.cos(np.dot(v,k*math.pi/256))
if k>0:
dct_1d=dct_1d-np.mean(dct_1d)
mat_dct_1d[:,k]=dct_1d/np.linalg.norm(dct_1d)
#随机测量
img_cs_1d=np.dot(Phi,im)
#OMP算法函数
def cs_omp(y,D):
L=math.floor(3*(y.shape[0])/4)
residual=y #初始化残差
index=np.zeros((L),dtype=int)
for i in range(L):
index[i]= -1
result=np.zeros((256))
for j in range(L): #迭代次数
product=np.fabs(np.dot(D.T,residual))
pos=np.argmax(product) #最大投影系数对应的位置
index[j]=pos
my=np.linalg.pinv(D[:,index>=0]) #最小二乘,看参考文献1
a=np.dot(my,y) #最小二乘,看参考文献1
residual=y-np.dot(D[:,index>=0],a)
result[index>=0]=a
return result
#重建
sparse_rec_1d=np.zeros((256,256)) # 初始化稀疏系数矩阵
Theta_1d=np.dot(Phi,mat_dct_1d) #测量矩阵乘上基矩阵
for i in range(256):
print('正在重建第',i,'列。')
column_rec=cs_omp(img_cs_1d[:,i],Theta_1d) #利用OMP算法计算稀疏系数
sparse_rec_1d[:,i]=column_rec;
img_rec=np.dot(mat_dct_1d,sparse_rec_1d) #稀疏系数乘上基矩阵
#显示重建后的图片
image2=Image.fromarray(img_rec)
image2.show()