机器学习——特征工程之特征选择

特征工程包括以下三种类型:

1.特征提取:从文字、图像、声音等非结构化特征中提取新信息作为特征。例如:从淘宝宝贝的名称中提取出 产品类别,产品颜色,是否是网红 产品等等。

2.特征创造:把现有特征进行组合或相互计算,形成新的特征。

3.特征选择:从所有的特征中,选择出对模型有意义的特征,来降低训练成本。

本文重点讲述特征选择的方法。

一、Filter过滤法

1.1方差过滤
通过特征本身的方差来筛选特征。例如:一个特征的方差很小,说明这个特征基本没什么差异,可能其中大多数值都一样,甚至整个特征取值都相同,那么这个特征对于样本区分没有什么作用。
所以,可以优先消除方差为0的特征。
方差过滤使用类 VarianceThreshold,VarianceThreshold有重要参数threshold,表示方差的阈值,表示舍弃所有方差小于threshold的特征,不填默认为0,即删除所有的记录都相同的特征。

from sklearn.feature_selection import  VarianceThreshold   #根据方差阈值过滤特征
selector=VarianceThreshold()   #实例化,默认方差为0
X_var0=selector.fit_transform(X)

如果过滤完方差为0的特征后,仍然剩下大量的特征,可以进一步过滤,例如我们想留下一半的特征,可以使用方差的中位数进行过滤。

import numpy as np
np.median(X.var().values)     
#X.var 读取每一列的方差,no.median找到这些方差的中位数
X_fsvar=VarianceThreshold(np.median(X.var().values)).fit_transform(X)

方差过滤的影响:
在这里插入图片描述

1.2相关性过滤
在特征选择时,我们希望能选出与标签相关且有意义的特征,为达到这个目的,可以通过相关性过滤来实现。相关性过滤包括三种方式:卡方、F检验、互信息。

1.2.1卡方过滤
卡方过滤是针对离散型数据(分类问题)的相关性过滤。
卡方检验类类feature_selection.chi2计算特征和标签之间的卡方统计量,依照卡方从高到低为特征排名。再结合feature_selection.SelectKBest来选出前K个分数最高的特征。借此出去独立于标签的无关特征。

另外,如果卡方检验检测到某个特征中所有的值都相同,会提示我们使用方差先进行方差过滤。

from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

#假设我知道要选择300个特征
X_fschi=SelectKBest(chi2,k=300).fit_transform(X_fsvar,Y)

如何选择k值呢?
一种方法是使用学习曲线,但是学习曲线运行需要很长的时间。
另一种更好的方法是:看p值选择k。
卡方检测的本质是推测两组数据之间的差异,其检测的原假设是“两组数据之间相互独立”。卡方检测返回卡方值p值两个统计量。
其中卡方值很难界定一个范围,但p值一般使用0.01或0.05作为显著性水平,即p值判定的边界。
在这里插入图片描述

chivalue,pvalues_chi=chi2(X_fsvar,Y)     #返回卡方值和P值
#k取多少?总特征的数量-p>0.05的数量
k=chivalue.shape[0]-(pvalues_chi>0.05).sum()

1.2.2 F检验
F检验是捕捉每个特征与标签线性关系的过滤方法。它既可以用于分类问题,也可以用于回归问题。
feature_selection.f_classif用于分类问题,feature_selection.f_regression用于回归问题。
和卡方检测相同,这两个类需要与SelectKBest连用。和卡方过滤一样,我们希望选取p值小于0.05或0.01的特征,这些特征与标签时显著线性相关的。

注意:F检测在数据服从正态分布时效果非常稳定,可以先将数据转换成正态分布的形式。

from sklearn.feature_selection import f_classif
F,p_values_f=f_classif(X_fsvar,Y)   #返回F值和p值
X_fschi=SelectKBest(f_classif,k=F.shape[0]-(p_values_f>0.05).sum()).fit_transform(X_fsvar,Y)

1.2.3 互信息法
互信息法是用于捕捉特征和标签之间的任意关系(线性和非线性)的过滤方法。
类feature_selection.mutual_info_classif用于分类:
类feature_selection.mutual_info_regression用于回归。

互信息法返回每个特征与目标之间互信息量的统计,这个估计量在[0,1]之间,为0表示两个变量独立,为1表示两个变量完全相关。

from sklearn.feature_selection import mutual_info_classif as MIC
result=MIC(X_fsvar,Y)
k=result.shape[0]-(result<=0).sum()

过滤法总结:
在这里插入图片描述

嵌入法

嵌入法是一种让算法自己决定使用哪些特征的方法,即特征选择和算法同时进行。在使用嵌入法时,首先使用机器学习的算法和模型进行训练,得到各个特征的权值系数,根据权值系数从大到小选择特征。这些权值系数往往代表特征对于模型的重要性,例如决策树的的feature_importances_属性,可以列出各个特征对模型的贡献,我们就可以基于这种贡献进行评估。

由于考虑特征对模型的贡献,无关的特征(需要相关性过滤)和无区分度的特征(需要方差过滤)都会因为缺乏对模型的贡献被删除掉。
在这里插入图片描述

然而,过滤法中使用的统计量可以使用统计知识和常识来查找范围(如p值应当低于显著性水平0.05),而嵌入法中使用的权值系数却没有这样的范围可找。这种情况下,模型权值系数就是我们的超参数, 我们或许需要学习曲线,或者根据模型本身的某些性质去判断这个超参数的最佳值究竟应该是多少。

另外,嵌入法引入了算法来挑选特征,因此其计算速度也会和应用的算法有很大的关系。如果采用计算量很大,计 算缓慢的算法,嵌入法本身也会非常耗时耗力。并且,在选择完毕之后,我们还是需要自己来评估模型。

from sklearn.feature_selection import  SelectFromModel
from sklearn.ensemble import RandomForestClassifier as RFC
RFC_=RFC(n_estimators=10,random_state=0) #首先实例化模型评估器
X_embedded=SelectFromModel(RFC_,threshold=0.005).fit_transform(X,Y)
#在这里我只想取出来有限的特征。0.005这个阈值对于有780个特征的数据来说,是非常高的阈值,
#因为平均每个特征 只能够分到大约0.001的feature_importances_

通过学习曲线来找最佳阈值:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import cross_val_score
(RFC_.fit(X,Y).feature_importances_).max()

threshold=np.linspace(0,(RFC_.fit(X,Y).feature_importances_).max(),20)
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()

在这里插入图片描述
之后在0~0.00134之间进一步细化学习曲线,来找最佳阈值。

score2=[]
for i in np.linspace(0,0.00134,20):
    X_embedded=SelectFromModel(RFC_,threshold=i).fit_transform(X,Y)
    once=cross_val_score(RFC_,X_embedded,Y,cv=5).mean()
    score2.append(once)
plt.figure(figsize=[20,5])
plt.plot(np.linspace(0,0.00134,20),score2)
plt.xticks(np.linspace(0,0.00134,20))
plt.show()

在这里插入图片描述
找到最佳阈值0.000564进行过滤:

X_embedded=SelectFromModel(RFC_,threshold=0.000564).fit_transform(X,Y)

比起要思考很多统计量 的过滤法来说,嵌入法可能是更有效的一种方法。然而,在算法本身很复杂的时候,过滤法的计算远远比嵌入法要 快,所以大型数据中,我们还是会优先考虑过滤法。

Wrapper包装法

包装法也是一个特征选择和算法训练同时进行的方法,与嵌入法十分相似,它也是依赖于算法自身的选择,比如 coef_属性或feature_importances_属性来完成特征选择。但不同的是,我们往往使用一个目标函数作为黑盒来帮 助我们选取特征,而不是自己输入某个评估指标或统计量的阈值。(这里的目标函数是指专业的数据挖掘算法).
包装法在初始特征集上训练评估器,并且通过 coef_属性或通过feature_importances_属性获得每个特征的重要性。然后,从当前的一组特征中修剪最不重要的 特征。在修剪的集合上递归地重复该过程,直到最终到达所需数量的要选择的特征.
最典型的目标函数是递归特征消除法,它反复创建模型,并在每次迭代时保留最佳特征或剔除最差特征,下一次迭代时, 它会使用上一次建模中没有被选中的特征来构建下一个模型,直到所有特征都耗尽为止。 然后,它根据自己保留或 剔除特征的顺序来对特征进行排名,最终选出一个最佳子集。

class sklearn.feature_selection.RFE (estimator, n_features_to_select=None, step=1, verbose=0)

#estimator是需要填写的实例化后的评估器,
#n_features_to_select是想要选择的特征个数,
#step表示每次迭 代中希望移除的特征个数。
#除此之外,RFE类有两个很重要的属性:
#.support_:返回所有的特征的是否最后被选中的布尔矩阵,
#以及.ranking_返回特征的按数次迭代中综合重要性排名

from sklearn.feature_selection import RFE RFC_ = RFC(n_estimators =10,random_state=0) selector = RFE(RFC_, n_features_to_select=340, step=50).fit(X, y)
 
selector.support_.sum()   ##返回特征是否被选中的布尔值
 
selector.ranking_   ##返回特征重要性排名
  
X_wrapper = selector.transform(X)
 
cross_val_score(RFC_,X_wrapper,y,cv=5).mean() 

也可以通过学习曲线来确定超参数:n_features_to_select的取值。

总结

过滤法更快速,但更粗糙;包装法和嵌入法更精确,比较适合具体到算法去调整,但计算量比较大,运行时间长。
当数据量很大的时候,优先使用方差过滤和互信息法调整,再上其他特征选择方法。
使用逻辑回归时,优先使用嵌入法。
使用支持向量机时,优先使用包装法。
迷茫的时候,从过滤法走起,看具体数据具体分析。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值