【3 - 特征工程】菜菜sklearn机器学习

 课程地址:《菜菜的机器学习sklearn课堂》_哔哩哔哩_bilibili

  • 第一期:sklearn入门 & 决策树在sklearn中的实现
  • 第二期:随机森林在sklearn中的实现
  • 第三期:sklearn中的数据预处理和特征工程
  • 第四期:sklearn中的降维算法PCA和SVD
  • 第五期:sklearn中的逻辑回归
  • 第六期:sklearn中的聚类算法K-Means
  • 第七期:sklearn中的支持向量机SVM(上)
  • 第八期:sklearn中的支持向量机SVM(下)
  • 第九期:sklearn中的线性回归大家族
  • 第十期:sklearn中的朴素贝叶斯
  • 第十一期:sklearn与XGBoost
  • 第十二期:sklearn中的神经网络

目录

概述

过滤法 Filter

(一)方差过滤

1、VarianceThreshold类

2、对模型的影响

3、选取超参数threshold

(二)相关性过滤 

1、卡方(feature_selection.chi2,仅分类)

选取超参数K(画学习曲线;看p值)

2、F检验(feature_selection.f_classif 分类;feature_selection.f_regression 回归)

3、互信息(feature_selection.mutual_info_classif 分类;feature_selection.mutual_info_regression 回归)

(三)过滤法总结

嵌入法 Embedding(过滤法的进化版)

feature_selection.SelectFromModel 

包装法 Wrapper(结合了过滤法和嵌入法)

feature_selection.RFE

feature_selection.RFECV

特征选择总结


概述

当数据预处理完成后,就是特征工程了。特征工程有三种:

  1. 特征提取(feature extraction):从非结构化数据中提取新信息作为特征
  2. 特征创造(feature creation):把现有特征进行组合,或相互计算,得到新特征
  3. 特征选择(feature selection):从所有特征中选择出有意义、对模型有帮助的特征

【3 - 特征工程】菜菜sklearn机器学习_第1张图片

本文主要讲特征选择 feature_selection,它完全独立于任何机器学习算法

特征选择的第一步是根据目标,用业务常识来选择特征,即理解业务。例如:

【3 - 特征工程】菜菜sklearn机器学习_第2张图片

以判断“是否存活”为目的

  • 票号、乘客登船的港口、乘客编号明显是无关特征,可以直接删除
  • 姓名、舱位等级、船舱编号,也基本可以判断是相关性比较低的特征
  • 性别、年龄、同船的兄弟姐妹数量、同船的父辈的数量,这些应该是相关性比较高的特征

但如果无法依赖对业务的理解来选择特征,有四种方法可以用来选择特征:

  1. 过滤法 Filter:包括方差过滤、相关性过滤(又可分为卡方过滤、F检验、互信息法)
  2. 嵌入法 Embedding
  3. 包装法 Wrapper:结合了过滤法和嵌入法
  4. 降维算法

数据集digit recognizor:

  • 42000行
  • 1785列(1列 label,784列pixel —— pixel 0~pixel 783)

【3 - 特征工程】菜菜sklearn机器学习_第3张图片

#导入数据,让我们使用digit recognizor数据来一展身手
 
import pandas as pd
data = pd.read_csv(r".\digit recognizor.csv")
 
X = data.iloc[:,1:]  # 特征,也即pixel
y = data.iloc[:,0]  # label
 
X.shape   # (42000, 784)

过滤法 Filter

根据各种统计检验中的分数以及相关性的各项指标来选择特征

  • 主要对象:需要遍历特征,或升维的算法
  • 主要目的:在维持算法表现的前提下,帮助算法降低计算成本

(一)方差过滤

1、VarianceThreshold类

通过特征本身的方差来筛选特征,优先消除方差为0的特征

  • 若一个特征本身的方差很小,就表示样本在这个特征上基本没有差异,可能特征中的大多数值都一样,甚至整个特征的取值都相同,那么这个特征对于样本区分没什么作用
  • 重要参数为threshold,表示方差的阈值 —— 舍弃所有方差小于threshold的特征,默认为0(即删除所有记录都相同的特征)
from sklearn.feature_selection import VarianceThreshold
selector = VarianceThreshold()                      #实例化,不填参数默认方差为0
X_var0 = selector.fit_transform(X)                  #获取删除不合格特征之后的新特征矩阵
 
#也可以直接写成 X = VairanceThreshold().fit_transform(X)
 
X_var0.shape   #(42000, 708)

pd.DataFrame(X_var0).head()

【3 - 特征工程】菜菜sklearn机器学习_第4张图片

删了方差为0的特征后还剩708个特征,还需要进一步特征选择

  • 如果知道需要多少个特征,方差也可以将特征选择一步到位,如:希望留下一半的特征,可以设定一个让特征总数减半的方差阈值,只要找到特征方差的中位数,再作为参数threshold的值输入即可
import numpy as np
# X.var()  每一列的方差,是Series
# np.median(X.var().values)  1352.286703180131
X_fsvar = VarianceThreshold(np.median(X.var().values)).fit_transform(X)

X_fsvar.shape   #(42000, 392)
  • 当特征是二分类时,特征的取值就是伯努利随机变量(0/1),这些变量的方差为:

【3 - 特征工程】菜菜sklearn机器学习_第5张图片

#若特征是伯努利随机变量,假设p=0.8,即二分类特征中某种分类占到80%以上的时候删除特征
X_bvar = VarianceThreshold(.8 * (1 - .8)).fit_transform(X)
X_bvar.shape   # (42000, 685)

 

2、对模型的影响

KNN和随机森林分别在方差过滤前、后运行效果运行时间的对比

  • KNN是K近邻算法中的分类算法,从模块neighbors 导入 KNeighborsClassifier
  • 原理:利用每个样本到其他样本点的距离来判断每个样本点的相似度,然后对样本进行分类
  • KNN必须遍历每个特征和每个样本,故特征越多,KNN的计算也会越缓慢
  • 样本a(xa1, xa2, xa3),样本b(xb1, xb2, xb3),两个样本点之间的距离为 sqrt( (xa1-xb1)**2 + (xa2-xb2)**2 + (xa3-xb3)**2 )

(1)导入模块并准备数据

【3 - 特征工程】菜菜sklearn机器学习_第6张图片

# KNN vs 随机森林在不同方差过滤效果下的对比
from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.neighbors import KNeighborsClassifier as KNN
from sklearn.model_selection import cross_val_score
import numpy as np

# 未过滤的数据
X = data.iloc[:,1:]
y = data.iloc[:,0]

# 使用中位数过滤后的数据
X_fsvar = VarianceThreshold(np.median(X.var().values)).fit_transform(X)

(2)KNN方差过滤前

python中的魔法命令,可以直接使用 %%timeit 来计算运行这个cell中的代码所需的时间


为了计算所需的时间,需要将这个cell中的代码运行很多次(通常是7次)后求平均值,因此运行%%timeit的时间会远远超过cell中的代码单独运行的时间

usageerror: line magic function "%%time" not found_南风有翼的博客-CSDN博客_line magic function `%%time` not found.

cross_val_score(KNN(),X,y,cv=5).mean()

%%timeit   # 将%%time放在代码块的顶行顶格,否则会报错
cross_val_score(KNN(),X,y,cv=5).mean()

 

(3)KNN方差过滤后

cross_val_score(KNN(),X_fsvar,y,cv=5).mean()

%%timeit
cross_val_score(KNN(),X_fsvar,y,cv=5).mean()

对于KNN,过滤后的效果十分明显:

  • 准确率稍有提升(0.965857142857143 —> 0.966) 
  • 平均运行时间大大减少(43.7s —> 29.8s),特征选择过后算法的效率上升

(4)随机森林方差过滤前

cross_val_score(RFC(n_estimators=10,random_state=0),X,y,cv=5).mean()

 

%%timeit
# 查看一下模型运行的时间
cross_val_score(RFC(n_estimators=10,random_state=0),X,y,cv=5).mean()

 

(5)随机森林方差过滤后

cross_val_score(RFC(n_estimators=10,random_state=0),X_fsvar,y,cv=5).mean()

%%timeit
# 查看一下模型运行的时间
cross_val_score(RFC(n_estimators=10,random_state=0),X_fsvar,y,cv=5).mean()

  • 随机森林的准确率略逊于KNN,但运行时间远远短于KNN
  • 方差过滤后,随机森林的准确率也微弱上升(0.9373571428571429 —> 0.9390476190476191),运行时间也微弱缩短(10.2s —> 8.59s)

为什么随机森林运行如此之快,且方差过滤对随机森林没有很大影响?

—— 因为两种算法的原理中涉及到的计算量不同

  • 最近邻KNN、单棵决策树、SVM、NN、回归算法,都需要遍历特征或升维来进行运算,故运算量大,需要时间长,故方差过滤这样的特征选择对它们来说尤为重要 —— 对于最近邻算法来说,特征越少,距离计算的维度就越少,模型明显会随着特征的减少变得轻量
  • 对于不需要遍历特征的算法,如随机森林(随机选取特征进行分枝),本身运算就非常快速,故特征选择对它来说效果平平 —— 无论过滤法如何降低特征的数量,随机森林也只会选取固定数量的特征来建模

【3 - 特征工程】菜菜sklearn机器学习_第7张图片

对受影响的算法来说,将方差过滤的影响总结如下:

【3 - 特征工程】菜菜sklearn机器学习_第8张图片

在我们的对比中使用的方差阈值是特征方差的中位数,因此属于阈值比较大,过滤掉的特征比较多的情况。但无论是KNN还是随机森林,在过滤掉一半特征之后,模型的精确度都上升了,这说明被过滤掉的特征在当前随机模式 random_state=0 下大部分是噪音 

3、选取超参数threshold

这里的方差阈值是一个超参数,要选定最优的超参数,可以画学习曲线,找模型效果最好的点(但这样做会耗费大量时间,现实中不会采用)

现实中一般只会使用阈值为0或者阈值很小的方差过滤,优先消除一些明显用不到的特征,再选择更优的特征选择方法继续削减特征数量

(二)相关性过滤 

选出与标签相关且有意义的特征

在sklearn中有三种方法来评判特征与标签之间的相关性:卡方、F检验、互信息 

1、卡方(feature_selection.chi2,仅分类)

计算每个非负特征(此处需要做数据预处理)和标签之间的卡方统计量,并按照卡方统计量由高到低为特征排名

feature_selection.SelectKBest 可以输入“评分标准”,选出前K个分数最高的特征

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

刚才已经验证过,当我们使用方差过滤筛选掉一半的特征后,模型的表现是提升的,因此在这里使用 threshold=中位数时完成的方差过滤的数据 来做卡方检验

(如果方差过滤后模型的表现反而降低了,就不使用方差过滤后的数据,而是使用原数据)

from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.model_selection import cross_val_score
from sklearn.feature_selection import SelectKBest  # 输入“评分标准”,选出前K个分数最高的特征
from sklearn.feature_selection import chi2
 
#假设在这里我知道我需要300个特征
X_fschi = SelectKBest(chi2, k=300).fit_transform(X_fsvar, y)   # SelectKBest(模型依赖的统计量,k=表示选出前k个统计量最大的特征,也即特征数)
X_fschi.shape   # (42000, 300)

# 验证一下模型的效果如何
cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()

模型的效果降低了,说明在设定 k=300 时删除了与模型相关且有效的特征 —> k值设置的太小,要么需要调整k值,要么放弃相关性过滤 (若模型表现提升,则说明相关性过滤有效,过滤掉了模型的噪音,这时保留相关性过滤的结果)

选取超参数K(画学习曲线;看p值)

方法1:学习曲线(运行时间长)

%matplotlib inline
import matplotlib.pyplot as plt
 
score = []
for i in range(390,200,-10):
    X_fschi = SelectKBest(chi2, k=i).fit_transform(X_fsvar, y)
    once = cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()
    score.append(once)
plt.plot(range(390,200,-10),score)
plt.show()

【3 - 特征工程】菜菜sklearn机器学习_第9张图片

随着K值的不断增加,模型的表现不断上升,这说明K越大越好,数据中所有的特征都是与标签相关的 

方法2:看p值

卡方检验的本质是推测两组数据之间的差异,其检验的原假设是“两组数据是相互独立的”,返回卡方值和P值两个统计量

  • 卡方值:很难界定有效的范围
  • P值:一般使用0.01或0.05作为显著性水平

【3 - 特征工程】菜菜sklearn机器学习_第10张图片

从特征工程角度,希望选取卡方值很大、P值小于0.05的特征(即和标签相关的特征)

调用SelectKBest之前,可以直接从chi2实例化后的模型中获得各个特征所对应的卡方值和P值

chivalue, pvalues_chi = chi2(X_fsvar,y)
chivalue
pvalues_chi

【3 - 特征工程】菜菜sklearn机器学习_第11张图片

所有特征的p值都是0,说明对于digit recognizor这个数据集来说,方差过滤已经把所有和标签无关的特征都剔除了,或这个数据集本身就不含与标签无关的特征。此时舍弃任何一个特征,都会舍弃对模型有用的信息,使模型表现下降

因此,在我们对计算速度满意时,不需要使用相关性过滤。若认为运算速度太缓慢,可以酌情删除一些特征,但会牺牲模型的表现

# k取多少?我们想要消除所有p值大于设定值,比如0.05或0.01的特征:
# 想保留的特征数量k = 特征数量-想要删除的特征数
k = chivalue.shape[0] - (pvalues_chi > 0.05).sum()   # chivalue.shape[0]为392(特征总数),pvalues_chi > 0.05返回的是布尔值,sum后就是True的数量(想要删除的特征数,即不相关的特征)
 
# X_fschi = SelectKBest(chi2, k=填写具体的k).fit_transform(X_fsvar, y)
# cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()

2、F检验(feature_selection.f_classif 分类;feature_selection.f_regression 回归)

F检验(ANOVA / 方差齐性检验):捕捉每个特征与标签之间的线性关系。F检验在数据服从正态分布时效果会非常稳定,故使用F检验过滤前会先将数据转换成服从正态分布的方式

  • 本质:寻找两组数据之间的线性关系
  • 原假设:数据不存在显著的线性关系
  • 返回:F值和p值两个统计量(希望选取p值<0.05/0.01的特征,这些特征与标签是显著线性相关的
  • 和卡方检验一样,这两个类需要和类SelectKBest连用,也可以直接通过输出的统计量来判断设置K的大小
from sklearn.feature_selection import f_classif
F, pvalues_f = f_classif(X_fsvar,y)
F
pvalues_f

F.shape   # (392,)

k = F.shape[0] - (pvalues_f > 0.05).sum()
k   # 392
 
# X_fsF = SelectKBest(f_classif, k=填写具体的k).fit_transform(X_fsvar, y)
# cross_val_score(RFC(n_estimators=10,random_state=0),X_fsF,y,cv=5).mean()

没有任何特征的p值>0.01,所有特征都是和标签相关的,故不需要相关性过滤

3、互信息(feature_selection.mutual_info_classif 分类;feature_selection.mutual_info_regression 回归)

互信息法:捕捉每个特征与标签之间的任意关系(包括线性和非线性关系)

  • 互信息法比F检验更强大,F检验只能找出线性关系,而互信息法可以找出任意关系
  • 返回:每个特征与目标之间互信息量的估计,在 [0,1] 之间,为0则表示两个变量独立,为1则表示两个变量完全相关
from sklearn.feature_selection import mutual_info_classif as MIC
 
result = MIC(X_fsvar,y)
result

【3 - 特征工程】菜菜sklearn机器学习_第12张图片

k = result.shape[0] - sum(result <= 0)   # result.shape[0]为392
k  # 392

# X_fsmic = SelectKBest(MIC, k=填写具体的k).fit_transform(X_fsvar, y)
# cross_val_score(RFC(n_estimators=10,random_state=0),X_fsmic,y,cv=5).mean()

所有特征的互信息量估计都>0,故所有特征都与标签相关  

(三)过滤法总结

基于过滤法的特征选择,包括方差过滤、基于卡方/F检验/互信息的相关性过滤

建议先使用方差过滤,然后使用互信息法来捕捉相关性

【3 - 特征工程】菜菜sklearn机器学习_第13张图片


嵌入法 Embedding(过滤法的进化版)

让算法自己决定使用哪些特征,即特征选择和算法训练同时进行

在使用嵌入法时,先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据权值系数从大到小选择特征

  • 权值系数往往代表了特征对于模型的某种贡献或重要性,比如决策树和树的集成模型中的feature_importances_ 属性,可以列出各个特征对树的建立的贡献
  • 基于这种贡献的评估,找出对模型建立最有用的特征

相比于过滤法,嵌入法的结果会更加精确到模型的效用本身,对于提高模型效力有更好的效果;同时,由于考虑特征对模型的贡献,因此无关的特征(需要相关性过滤的特征)和无区分度的特征(需要方差过滤的特征)都会因为缺乏对模型的贡献而被删除

【3 - 特征工程】菜菜sklearn机器学习_第14张图片

嵌入法的缺点:

  1. 权值系数为0的特征对模型丝毫没有作用,但当大量特征都对模型有贡献且不一时,很难界定有效的临界值,故模型权值系数是超参数
  2. 引入了算法来挑选特征,故计算速度和应用的算法有很大关系;且在选择完毕之后,还是需要自己来评估模型

feature_selection.SelectFromModel 

SelectFromModel 是一个元变换器,可以与任何在拟合后具有 coef_ 、 feature_importances_ 属性,或参数中可选惩罚项的评估器一起使用。例如:

  • 随机森林和树模型就有属性 feature_importances_
  • 逻辑回归带有 l1 和 l2 惩罚项
  • 线性支持向量机也支持 l2惩罚项

(1)对于有 feature_importances_ (取值范围是[0,1])的模型来说,若重要性低于提供的阈值参数,则认为这些特征不重要并被移除

(2)对于使用惩罚项的模型来说,正则化惩罚项越大,特征在模型中对应的系数就会越小;当正则化惩罚项大到一定程度时,部分特征系数会变成0,这部分系数是可以筛掉的。即选择特征系数较大的特征

  • SVM和LR使用参数C来控制返回的特征矩阵的稀疏性,参数C越小,返回的特征越少
  • Lasso回归用参数α来控制返回的特征矩阵,α的值越大,返回的特征越少

【3 - 特征工程】菜菜sklearn机器学习_第15张图片

例:使用随机森林为例,使用学习曲线寻找最佳特征值

【3 - 特征工程】菜菜sklearn机器学习_第16张图片 

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)   # SelectFromModel(RFC_,threshold=0.005)为嵌入法的实例化
 
#在这里我只想取出来有限的特征。0.005这个阈值对于有784个特征的数据来说,是非常高的阈值,因为平均每个特征只能够分到大约0.001的feature_importances_
 
X_embedded.shape   # (42000, 47)
#模型的维度明显被降低了


#同样的,我们也可以画学习曲线(横轴:某个范围内超参数的取值;纵轴:模型的表现)来找最佳阈值 
import numpy as np
import matplotlib.pyplot as plt
 
RFC_.fit(X,y).feature_importances_

# range(开头,结尾,步长)
# np.linspace(开头,结尾,数量)
threshold = np.linspace(0,(RFC_.fit(X,y).feature_importances_).max(),20)   # 选取最小值和最大值中间的有限个数,是学习曲线的x轴
threshold  # 阈值越大,被砍掉的特征就越多

【3 - 特征工程】菜菜sklearn机器学习_第17张图片

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()

【3 - 特征工程】菜菜sklearn机器学习_第18张图片

从图像上来看,随着阈值越来越高,模型的效果逐渐变差,被删除的特征越来越多,信息损失也逐渐变大 

# 从中挑选一个数值来验证一下模型的效果
X_embedded = SelectFromModel(RFC_,threshold=0.001).fit_transform(X,y)
X_embedded.shape  # (42000, 279)
cross_val_score(RFC_,X_embedded,y,cv=5).mean()   # 0.9386904761904763

和其他调参一样,可以在第一条学习曲线后选定一个范围,使用细化的学习曲线来找到最佳值

score2 = []
for i in np.linspace(0,0.001,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.001,20),score2)
plt.xticks(np.linspace(0,0.001,20))
plt.show()
【3 - 特征工程】菜菜sklearn机器学习_第19张图片 最高点0.000158已经将模型效果提升到了94.1%以上
X_embedded = SelectFromModel(RFC_,threshold=0.000158).fit_transform(X,y)
X_embedded.shape   # (42000, 421)
cross_val_score(RFC_,X_embedded,y,cv=5).mean()  # 0.9411428571428571

#我们可能已经找到了现有模型下的最佳结果,如果我们调整一下随机森林的参数呢?
cross_val_score(RFC(n_estimators=100,random_state=0),X_embedded,y,cv=5).mean()

 

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


包装法 Wrapper(结合了过滤法和嵌入法)

特征选择和算法训练同时进行,与嵌入法十分相似,也是依赖于算法自身的选择,比如 coef_ 属性或 feature_importances_ 属性来完成特征选择

  1. 在初始特征集上训练评估器,通过 coef_ 属性或 feature_importances_ 属性获得每个特征的重要性
  2. 从当前的一组特征中修剪最不重要的特征
  3. 在修剪的集合上递归地重复该过程,直到最终达到所需数量的要选择的特征

【3 - 特征工程】菜菜sklearn机器学习_第20张图片

上图中的算法,不是我们最终用来导入数据的分类或回归算法,而是专业的数据挖掘算法(即目标函数),这些数据挖掘算法的核心功能就是选取最佳特征子集最典型的目标函数是递归特征消除法(Recursive feature elimination, 简写为RFE)。它是一种贪婪的优化算法,旨在找到性能最佳的特征子集。它反复创建模型,并在每次迭代时保留最佳特征或剔除最差特征,下一次迭代时,它会使用上一次建模中没有被选中的特征来构建下一个模型,直到所有特征都耗尽为止。 然后,它根据自己保留或剔除特征的顺序来对特征进行排名,最终选出一个最佳子集

不同点:

  • 往往使用一个目标函数作为黑盒来选取特征,而不是自己输入某个评估指标或统计量的阈值
  • 嵌入法是多次使用全部特征,包装法是只使用上次已经被舍弃的特征中剩下的特征,每一轮特征相比上一轮都会减少
  • 计算成本:嵌入法 > 包装法 > 过滤法
  • 包装法的效果是所有特征选择方法中最利于提升模型表现的,它可以使用很少的特征达到很优秀的效果。除此之外,在特征数目相同时,包装法和嵌入法的效果能够匹敌,不过它比嵌入法算得更快,虽然它的计算量也十分庞大,不适用于太大型的数据。相比之下,包装法是最能保证模型效果的特征选择方法

 

feature_selection.RFE

参数:

  • estimator:实例化后的评估器
  • n_features_to_select:想要选择的特征个数
  • step:每次迭代中希望移除的特征个数

属性:

  • .support_:返回所有的特征最后是否被选中的布尔矩阵,选中了就是True,没选中就是False
  • .ranking_:返回特征按次数迭代中综合重要性的排名,排名越前,特征越重要
from sklearn.feature_selection import RFE
RFC_ = RFC(n_estimators =10,random_state=0)
selector = RFE(RFC_, n_features_to_select=421, step=50).fit(X, y)  # 421是之前嵌入法选择出的最佳特征数

selector.support_.sum()  # 就是n_features_to_select的值
selector.ranking_   # 可以有多个特征重要性相同,故排名一样

【3 - 特征工程】菜菜sklearn机器学习_第21张图片

X_wrapper = selector.transform(X)   # 使用包装法得到的特征矩阵
cross_val_score(RFC_,X_wrapper,y,cv=5).mean()   # 0.9395

对包装法画学习曲线:

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()

【3 - 特征工程】菜菜sklearn机器学习_第22张图片

在包装法下面应用50个特征时,模型的表现就已经达到了90%以上,比嵌入法和过滤法都高效很多(包装法是最容易在最小的特征数量状况下找到最佳的模型表现的方法) 

feature_selection.RFECV

在交叉验证循环中执行RFE以找到最佳数量的特征,增加参数cv(交叉验证次数),其他用法同RFE


特征选择总结

过滤法更快速,但更粗糙。迷茫的时候,从过滤法走起

包装法和嵌入法更精确,比较适合具体到算法去调整,但计算量比较大,运行时间长

  • 数据量很大的时候,优先使用方差过滤和互信息法调整,再上其他特征选择方法
  • 使用逻辑回归时,优先使用嵌入法
  • 使用支持向量机时,优先使用包装法
特征选择只是特征工程中的第一步。真正的高手,往往使用 特征创造或特征提取 来寻找高级特征

你可能感兴趣的:(机器学习,sklearn,python)