数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已,由此可以看出特征选择的重要性。特征选择的本质就是对一个给定特征子集的优良性通过一个特定的评价标准进行衡量,通过特征选择,原始特征集合中的冗余特征和不相关特征被除去。而有用特征得以保留。

下面说几种用到的方法。

Filter过滤法

方差过滤

如果一个特征本身方差很小,那么就表示样本在这个特征上基本没有差异,那么就可以认为这个特征作用不大,所以需要通过方差过滤来消除方差小于某一个阈值的特征,在 sklearn 中我们使用 VarianceThreshold 类来选择特征。其中VarianceThreshold 中的参数表示 threshold 表示方差的阈值,表示舍弃所有方差小于 threshold 的特征,如果不填写,默认为 0。

1
2
3
4
5
6
from sklearn.feature_selection import VarianceThreshold

# 舍弃方差小于0.5的特征
var=VarianceThreshold(threshold=0.5)
df=var.fit_transform([[0,2,0,3],[0,1,4,3],[0,1,1,3]])
print(df)

相关性过滤

特征与标签有相关性,才能为模型提供大量信息。如果特征与标签无关,可能会给模型带来噪音。常见的相关性过滤为一下三种。

卡方过滤(针对离散型变量)
卡方检验就是统计样本的实际观测值与理论推断值之间的偏离程度,实际观测值与理论推断值之间的偏离程度决定卡方值的大小,如果卡方值越大,二者偏差程度越大;反之,二者偏差越小;若两个值完全相等时,卡方值就为0,表明理论值完全符合。

卡方检验类 feature_selection.chi2 计算每个非负特征和标签之间的卡方统计量,并依照卡方统计量由高到低为特征排名。再结合 feature_selection.SelectKBest 这个可以输入”评分标准“来选出前K个分数最高的特征的类,可以借此除去最可能独立于标签,和分类目的无关的特征。

1
2
3
4
5
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

# 选择K-10个最好的特征,返回选择特征后的数据
X_fschi = SelectKBest(chi2, k=10).fit_transform(X_fsvar, y)

F检验(离散型和回归型变量均适合)
F检验,又称方差齐性检验,是用来捕捉每个特征与标签之间的线性关系的过率方法。F检验在数据服从正态分布的适合是非常稳定的,因此,如果使用F检验过滤,我们会先将数据转化为服从正太分布的方式。F检验的本质是寻找两组数据之间的线性关系,其原假设是”数据不存在显著的线性关系“。它返回F值和 p 值两个统计量。和卡方过滤一样,我们希望选取 p值小于 0.05 或 0.01 的特征,这些特征与标签时显著线性相关的,而 p 值大于 0.05 或 0.01 的特征则被我们认为是和标签没有显著线性关系的特征,应该被删除。

互信息法
互信息法是用来捕捉每个特征与标签之间的任意关系(包括线性和非线性关系)的过滤方法。互信息法不返回 p 值或 F 值类似的统计量,它返回每个特征与目标之间的互信息量的估计,这个估计量在 [0,1] 之间取值,为 0 则表示两个变量独立,为 1 则表示两个变量完全相关。

Embedded嵌入法

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

1
2
3
4
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)

Wrapper包装法

包装法通过不断排除特征或者不断选择特征,并对训练得到的模型效果进行打分,通过预测效果评分来决定特征的去留。包装法在 feature_selection 中使用 RFE 类来操作,下面是 RFE 的参数。

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

参数说明:

  • estimator 是需要填写的实例化后的评估器;
  • n_features_to_select 是想要选择的特征个数;
  • step 表示每次迭代中希望移除的特征个数。

RFE类有两个很重要的属性,support_ 返回所有的特征的是否最后被选中的布尔矩阵_,以及 _ranking 返回特征的按数次迭代中综合重要性的排名。类 feature_selection.RFECV 会在交叉验证循环中执行RFE以找到最佳数量的特征,增加参数cv。

1
2
3
4
5
6
7
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()