11.1 编程实现 Relief 算法,并在西瓜数据集上测试。
Relief 是过滤式特征选择算法,根据设计的 “相关统计量” 来度量特征的重要性。该方法和后续的学习器无关,只根据数据集就可完成特征选择。相关的思想理论介绍见书P249-250
代码实现如下:
import pandas as pd
import numpy as np
class Relief:
def readData(self):
dataset = pd.read_excel('./WaterMelon_3.0.xlsx',encoding = 'gbk') # 读取数据
self.Attributes = dataset.columns[1:-1] #所有属性的名称
#print(self.Attributes)
dataset = np.matrix(dataset)
dataset = dataset[:,1:]
m,n = np.shape(dataset) # 得到数据集大小
#print(dataset)
dataset[:,n-3:n-1] = (dataset[:,n-3:n-1]-np.min(dataset[:,n-3:n-1],0))/\
(np.max(dataset[:,n-3:n-1],0)-np.min(dataset[:,n-3:n-1],0)) # 连续属性规范化
self.goodindex = np.where(dataset[:,n-1]=='是')[0] # 好瓜的索引
self.badindex = np.where(dataset[:,n-1]=='否')[0] # 坏瓜的索引
self.dataset = dataset
# 计算每个样本之间的距离
def getDist(self):
m,n = np.shape(self.dataset)
distance = np.ones([m,m])
for i in range(m):
distance[i,i] = np.inf
for j in range(i+1,m):
dis = 0
for k in range(n-1):
if type(self.dataset[i,k])== str: # 离散属性
dis = dis + 1 - np.int(self.dataset[i,k]==self.dataset[j,k])
else: # 连续属性
dis = dis + pow((self.dataset[i,k]-self.dataset[j,k]),2)
distance[i,j] = dis
distance[j,i] = dis
self.distance = distance
# 过滤
def fliter(self):
m,n = np.shape(self.dataset)
delte = np.zeros([n-1])
for i in range(m): # 依次对每一个样本进行
delte = delte + self.getdelet(i)
return delte
# 计算一个样本中所有属性的权值delte
def getdelet(self,i):
m,n = np.shape(self.dataset)
distance = self.distance[i,:] # 该样本i到每一个样本的距离
gooddis = distance[self.goodindex] # 到好瓜距离
baddis = distance[self.badindex] # 到坏瓜距离
good = dict(zip(gooddis,self.goodindex)) # 生成字典,键为距离,值为样本索引
bad = dict(zip(baddis,self.badindex))
if self.dataset[i,-1] == '是': # 样本i是好瓜
minh = np.min(gooddis) # 同类中最小距离
indexh = good[minh] # 最小距离对应的样本索引
minm = np.min(baddis) # 不同类中最小距离
indexm = bad[minm] # 不同类中最小距离对应的索引
else:
minh = np.min(baddis) # 同类
indexh = bad[minh]
minm = np.min(gooddis) # 不同类
indexm = good[minm]
delte = []
for j in range(n-1): # 遍历每一个属性,进行计算
if type(self.dataset[i,j])== str: # 离散属性
dh = 1 - np.int(self.dataset[i,j]==self.dataset[indexh,j]) # 同类
dm = 1 - np.int(self.dataset[i,j]==self.dataset[indexm,j]) # 不同类
else: # 连续属性
dh = np.float64(pow((self.dataset[i,j]-self.dataset[indexh,j]),2)) # 同类
dm = np.float64(pow((self.dataset[i,j]-self.dataset[indexm,j]),2)) # 不同类
delte.append(-dh+dm)
return delte # 返回的是样本i计算得到的每一个属性上的权值
def getAttr(self,delte):
dic = dict(zip(self.Attributes,delte)) # 得到字典
dd = sorted(dic.items(),key=lambda item:item[1],reverse=True) # 根据值的大小进行排序,倒序
for i,j in dd:
print(i+':'+str(j),end='\t')
def main():
relief = Relief()
relief.readData()
relief.getDist()
delte = relief.fliter()
relief.getAttr(delte)
if __name__ == '__main__':
main()
最终得到的每个属性的权值(重要性程度)如下:
纹理:9.0 脐部:7.0 根蒂:4.0 含糖率:2.04491655411 密度:-0.500966445714 敲声:-1.0 触感:-4.0 色泽:-7.0
11.2 Relief-F 算法描述
输入:
数据集D
过程:
1. 将数据集中连续属性取值规范化到[0,1]
2. 计算数据集D中各类样本所占的比例 p_l
3. 计算数据集D中每一对样本之间的距离distance
4. thete = [0,0,……,0] , 表示每一个属性的权值
5. for x_i in D:
6. d_nh,d_nm = [0,0,……,0] , 表示通过样本 x_i 在所有属性上计算得到的权值,对应于式11.4的前后两部分
7. 根据distance矩阵找出每个分类类别中与 x_i 距离最近的样本,构成集合 xmin
8. for x_j in xmin:
9. if(x_i和x_j类别相同):d_nh = diff(x_i,x_j)^2
10. else: d_nm = d_nm + p_l * diff(x_i,x_j)^2 其中,p_l是x_j 所在类别的比例
11. thete = thete + (-d_nh+d_nm)
输出:thete
11.3 设计一个可以考虑每一对属性重要性的改进算法。
可以将所有的属性两两配对,然后将其看成一个整体,将整体带入类似于原来的 Relief 算法中进行运算,最终得到针对每一对的权重,即可实现每一对属性重要性的衡量。 (好像有点 low, 但是确实想不到其他的好的方法,如有什么新的思路还请指教!)
11.4 设计一个算法,即便有运行时间限制,LVW 算法也一定能给出解。
该算法的结束条件是 连续 t 次随机产生的特征子集在学习器上的效果都比当前的特征子集差。但是当数据集和特征集都很大时,这个条件很难满足,所以为了可以在规定的时间内结束算法,我们可以再人为设定一个最大的迭代次数,当达到最大的迭代次数之后,不论当前状态如何,都将当前的最佳特征子集返回。
11.5 L1正则化在何种情形下不能产生稀疏解。
L1正则化之所以可以产生稀疏解,主要是因为平方误差项等值线与L1等值线的第一个交点位于坐标轴上,如书上图11.2所示,当平方误差项等值线的曲率比较大时,就会导致其与L1等值线的第一个交点不再位于坐标轴上,此时就无法产生稀疏解。
11.6 试述岭回归和SVM的联系。
相同点: 两者的优化目标中都有权重参数项,都想得到较小的权重。
不同点:
岭回归的目标函数主要是 累积平方误差,主要的目的是减小这个误差。而后面加的权重参数项只是一个正则化的手段,以此来防止过拟合。整体上看就是想要实现 在尽量小的权重参数取值下尽可能地降低累积平方误差,两者之间通过系数进行权衡。
SVM则不同,它是直接将权重参数的二范数作为优化目标,没有考虑累积平方误差,而对应的约束条件是保证每一个样本和分隔线之间具有足够的间隔。 所以整体上是为了实现 在保证所有的样本都可以以指定的间隔分离的条件下(必须达到这个条件),取具有最小二范数值的权重参数。 所以,SVM 的优化目标决定了样本必须线性可分,否则就无法实现。
11.7 直接求解 L0 范数正则化会遇到的困难。
L0 范数是不连续的,而且是非凸函数,无法通过优化直接求解,必须采用遍历的方式,因此导致这个问题是个NP难问题。
11.8 L1范数求解最小化问题式 11.14 的推导。
参考自: https://blog.csdn.net/icefire_tyh/article/details/52254580
11.9 试述字典学习与压缩感知对稀疏稀疏性利用的异同。
字典学习使样本转化为稀疏表示的形式,是为了利用稀疏性来使学习任务得到简化,使模型的复杂度得到降低,从而可以学习到一个对于当前的学习任务比较好的一个学习器。
而压缩感知主要是想利用信号本身所具有的稀疏性,从而实现从部分观测样本中恢复出原始信号的目的。