西⽠书习题11.1编程实现Relief算法特征选择、正则化总结西⽠书第⼗⼀章,主要讲了⼀下特征选择的⽅法,通常来说,有很多冗余特征,如果能把这些特征从我们的数据集中筛选出去,那么可以极⼤地提⾼我们的程序运⾏效率,当然有的时候我们还需要⼈为保留或者创造⼀些冗余特征,当且仅当这些冗余特征恰好对应了完成任务所需要的“中间概念”。⽐如要求⼀个⽴⽅体的体积时,输⼊数据只有长宽⾼,如果能⼈为创造⼀个“底⾯积”或者“侧⾯积”这样的冗余特征,那么更容易求解,这个冗余特征要分情况来确定。
这⾥我们不主要探讨冗余特征,⽽是多说⼀些如何筛选特征,也就是搜索⼀个特征⼦集,让这个⼦集训练出来的模型最棒,这个问题显然是NP的,⼀切搜索⽅法都有局限性,那么⽬前我们常⽤的特征选择⽅法有三种:过滤式filter、包裹式wrapper、嵌⼊式embedding。
过滤式选择:
先对数据集进⾏特征选择,再训练学习器,特征选择与后续学习⽆关,我这个Relief算法就是⼀种经典的过滤式选择,Relief是先把每个个体的最近邻求出来,这⾥有⼏个分类结果就要求⼏个对应的近邻,分为猜中近邻(near-hit)和猜错近邻(near-miss),然后根据式11.3求⼀下各个属性的值就⾏,分量值越⼤,对应属性的能⼒就越强。
包裹式选择:
直接把最终要使⽤的学习器的性能作为特征⼦集的评价准则,量⾝定做特征⼦集,这⾥就是固定好学习器,然后随机的选⼦集,哪个⼦集误差⼩就⽤哪个,著名的有LAW拉斯维加斯wrapper。
嵌⼊式选择:
说⽩了就是⽤L1正则化来求解⽬标函数,⽐较容易得到稀疏解,然后有的分量可能取值就为0了,于是这个分量对应的属性就相当于被筛掉了。假如我是一只猫
这⾥重点说⼀下正则化:
正则化是⽤来防⽌过拟合的⼯具,样本特征多,样本数量少,很容易陷⼊过拟合,这时候我们加⼀个正则化项,希望求到⼀个尽量平滑、权值和较⼩的解,这⾥通常有L2、L1、L0正则化,L2范数就是求w的欧式距离,L1对应曼哈顿距离,L0对应切⽐雪夫距离,这些距离都是类闵可夫斯基距离,就是各个分量差的p次⽅之和再开p次根,在⼆维空间⾥,如果距离为1,欧式距离可以理解为⼀个半径为1的圆,曼哈顿距离能画出⼀个旋转了45度的正⽅形,对⾓线长度是2,边长根2,切⽐雪夫就是⼀个边长为2的正⽅形,在三维空间⾥,若距离为
1,L2就是半径为1的球,L1就是⼀个边长根2的正⼋⾯体,L0就是⼀个边长为2的⽴⽅体。于是L1和L0更容易在顶点处与误差项相交(L0⽐L1更容易),从⽽获得稀疏解,⽽L2更容易获得各个分量都很
均衡的解。这⾥我们通常不⽤L0正则,因为L0正则是不连续的,没法求导,⽆法优化求解。(书P253页的图很棒)
Relief的代码:
这⾥我把西⽠数据集都处理成连续值了,因为要求最近邻,必须要把数据处理⼀下,离散值要处理成单独的⼀个属性或者是连续值。
import numpy as np
import pandas as pd
ad_csv('/home/parker/watermelonData/watermelon_3.csv', delimiter=",")
del datat['编号']怎么创建
干干净净
操妇女print(datat)
attributeMap={}
attributeMap['浅⽩']=0
attributeMap['青绿']=0.5
attributeMap['乌⿊']=1
attributeMap['蜷缩']=0
眼睛动漫attributeMap['稍蜷']=0.5
attributeMap['硬挺']=1
attributeMap['沉闷']=0
attributeMap['浊响']=0.5
attributeMap['清脆']=1
attributeMap['模糊']=0
attributeMap['稍糊']=0.5
兰蔻怎么样attributeMap['清晰']=1
包装设计展开图
attributeMap['凹陷']=0
attributeMap['稍凹']=0.5
attributeMap['平坦']=1
attributeMap['硬滑']=0
attributeMap['软粘']=1
attributeMap['软粘']=1
attributeMap['否']=0
attributeMap['是']=1
data=datat.values
m,n=np.shape(data)
for i in range(m):
for j in range(n):
if data[i,j] in attributeMap:
data[i,j]=attributeMap[data[i,j]]
el: data[i,j]=round(data[i,j],3)
X=data[:,:-1]
y=data[:,-1]
m,n=np.shape(X)
# print(X,y)
s((m,2))#near[i,0] is nearHit, near[i,1] is nearMiss
# print(near)
def distance(x1,x2):
return sum((x1-x2)**2)
for i in range(m):
hitDistance=99999 #init as INF
missDistance=99999
for j in range(m):
if j==i:continue
curDistance=distance(X[i],X[j])
if y[i]==y[j] and curDistance<hitDistance:
hitDistance=curDistance
near[i,0]=j
if y[i]!=y[j] and curDistance<missDistance:
的学校missDistance=curDistance
near[i,1]=j
#P250--(11.3)
s(n)
for j in range(n):
for i in range(m):
relief[j]+=(X[i,j]-X[int(near[i,1]),j])**2-(X[i,j]-X[int(near[i,0]),j])**2
print(relief)
结果我们发现纹理得分4.25,很关键,这⼀点跟ID3决策树的结果是⼀致的,然后脐部、⾊泽也很重要,GiniIndex决策树也把这两项作为树根了,含糖率重要性也很⼤,这也符合我们的认知,总之我们发现这个Relief算法还真不错。