sklearn之特征选择

Embedded嵌入法

嵌入法是一种让算法自己决定使用哪些特征的方法,即特征选择和算法训练同时进行。在使用嵌入法时,我们先使用某些机器学习的算法和全部特征对模型进行训练,得到各个特征的权值系数,根据权值系数从大到小选择特征。这些权值系数往往代表了特征对于模型的某种贡献或某种重要性,比如决策树和树的集成模型中的feature_importances_属性,可以列出各个特征对树的建立的贡献,我们就可以基于这种贡献的评估,找出对模型建立最有用的特征。
嵌入法的结果会更加精确到模型的效用本身,对于提高模型效力有更好的效果。并且,由于考虑特征对模型的贡献,因此无关的特征(需要相关性过滤的特征)和无区分度的特征(需要方差过滤的特征)都会因为缺乏对模型的贡献而被删除掉。
但当大量特征都对模型有贡献且贡献不一时,我们就很难去界定一个有效的临界值。这种情况下,模型权值系数就是我们的超参数,我们或许需要学习曲线,或者根据模型本身的某些性质去判断这个超参数的最佳值究竟应该是多少。每个算法,都会提到这个算法中的特征工程是如何处理,包括具体到每个算法的嵌入法如何使用

sklearn.feature_selection.SelectFromModel (estimator, threshold=None, prefit=False, norm_order=1,max_features=None)
SelectFromModel是一个元变换器,可以与任何在拟合后具有coef_,feature_importances_属性或参数中可选惩罚项的评估器一起使用(比如随机森林和树模型就具有属性feature_importances_,逻辑回归就带有l1和l2惩罚项,线性支持向量机也支持l2惩罚项)。
对于有feature_importances_的模型来说,若重要性低于提供的阈值参数,则认为这些特征不重要并被移除。feature_importances_的取值范围是[0,1],如果设置阈值很小,比如0.001,就可以删除那些对标签预测完全没贡献的特征。如果设置得很接近1,可能只有很少的特征会被留下
##########参数说明(重点考虑前两个参数)
1.estimator
使用的模型评估器,只要是带feature_importances_或者coef_属性,或带有l1和l2惩罚项的模型都可以使用
2.threshold
特征重要性的阈值,重要性低于这个阈值的特征都将被删除
3.prefit
默认False,判断是否将实例化后的模型直接传递给构造函数。如果为True,则必须直接调用fit和transform,不能使用fit_transform,并且SelectFromModel不能与cross_val_score,GridSearchCV和克隆估计器的类似实用程序一起使用。
4.norm_order
k可输入非零整数,正无穷,负无穷,默认值为1 在评估器的coef_属性高于一维的情况下,用于过滤低于阈值的系数的向量的范数的阶数。
5.max_features
在阈值设定下,要选择的最大特征数。要禁用阈值并仅根据max_features选择,请设置threshold = -np.inf
# 手写数字识别数据集
from sklearn.feature_selection import SelectFromModel
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
import matplotlib.pyplot as plt
import numpy as np

RFC = RandomForestClassifier(n_estimators=10,random_state=0) # 随机森林实例化
x_embedded = SelectFromModel(RFC,threshold=0.005).fit_transform(x , y) # 全部特征和全部标签
print(x_embedded.shape) # (42000, 47) 原785特征

# 画学习曲线来找最佳阈值
threshold = np.linspace(0,(RFC.fit(x,y).feature_importances_).max(),20)
# array([0.        , 0.00067177, 0.00134354, 0.00201531, 0.00268707,
#        0.00335884, 0.00403061, 0.00470238, 0.00537415, 0.00604592,
#        0.00671769, 0.00738945, 0.00806122, 0.00873299, 0.00940476,
#        0.01007653, 0.0107483 , 0.01142007, 0.01209183, 0.0127636 ])
score = []
for i in threshold:
    x_embedded = SelectFromModel(RFC,threshold=i).fit_transform(x,y)
    once = cross_val_score(RFC,x_embedded,y,cv=5).mean()
    score.append(once)
plt.plot(threshold,score)
plt.show()

wrapper包装法

包装法也是一个特征选择和算法训练同时进行的方法,与嵌入法十分相似,它也是依赖于算法自身的选择,比如coef_属性或feature_importances_属性来完成特征选择。但不同的是,我们往往使用一个目标函数(专门选取特征的算法)作为黑盒来帮助我们选取特征,而不是自己输入某个评估指标或统计量的阈值。包装法在初始特征集上训练评估器,并且通过coef_属性或通过feature_importances_属性获得每个特征的重要性。然后,从当前的一组特征中修剪最不重要的特征。在修剪的集合上递归地重复该过程,直到最终到达所需数量的要选择的特征。区别于嵌入法的一次训练解决所有问题,包装法要使用特征子集进行多次训练,因此它所需要的计算成本是最高的。
最典型的目标函数是递归特征消除法(Recursive feature elimination, 简写为RFE)。它是一种贪婪的优化算法,旨在找到性能最佳的特征子集。 它反复创建模型,并在每次迭代时保留最佳特征或剔除最差特征,下一次迭代时,它会使用上一次建模中没有被选中的特征来构建下一个模型,直到所有特征都耗尽为止。然后,它根据自己保留或剔除特征的顺序来对特征进行排名,最终选出一个最佳子集。包装法的效果是所有特征选择方法中最利于提升模型表现的,它可以使用很少的特征达到很优秀的效果。除此之外,在特征数目相同时,包装法和嵌入法的效果能够匹敌,不过它比嵌入法算得更快,但是他的计算量也比较庞大,所以也不适用于太大型的数据。相比之下,包装法是最能保证模型效果的特征选择方法。

feature_selection.RFE
sklearn.feature_selection.RFE (estimator, n_features_to_select=None, step=1, verbose=0)
1.estimator
是需要填写的实例化后的评估器,
2.n_features_to_select
是想要选择的特征个数
3.step
表示每次迭代中希望移除的特征个数。
除此之外,RFE类有两个很重要的属性
1.support_ 返回所有的特征的是否最后被选中的布尔矩阵
2..ranking_ 返回特征的按数次迭代中综合重要性的排名。
类feature_selection.RFECV会在交叉验证循环中执行RFE以找到最佳数量的特征,增加参数cv,其他用法都和RFE一模一样。
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import RFE
import matplotlib.pyplot as plt
import numpy as np
RFC = RandomForestClassifier(n_estimators=10,random_state=0)
selector = RFE(RFC,n_features_to_select=340,step=50).fit(x,y)
print(selector.support_.sum()) # 返回所有特征是否被选中的布尔矩阵 求和一共340个特征被选中
print(selector.ranking_) # 所有特征的重要性排名 重要性相同排名就会一样
x_wrapper = selector.transform(x)
score = cross_val_score(RFC,x_wrapper,y,cv=5).mean()

# 包装法学习曲线来找最佳阈值
score = []
for i in range(1,751,50):
    x_wrapper = RFE(RFC,n_features_to_select=i, step=50).fit_transform(x,y)
    once = cross_val_score(RFC,x_wrapper,y,cv=5).mean()
    score.append(once)
plt.figure(figsize=[20,5])
plt.plot(range(1,751,50),score)
plt.xticks(range(1,751,50))
plt.show()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值