本文涉及的是特征选择。其实特征选择只是特征工程中的第一步。更深入的是使用特征创造或特征提取来寻找高级特征。
除了对业务的理解,有四种方法可以用来选择特征:
过滤法,嵌入法,包装法,和降维算法。
下面是通过代码对除降维之外的算法进行实操。
import pandas as pd data = pd.read_csv("digit recognizor.csv") data.head()
可以看到有785-1个特征,对它们做特征选择。
x = data.iloc[:,1:] y = data.iloc[:,0]
1.过滤法之方差过滤
from sklearn.feature_selection import VarianceThreshold selector = VarianceThreshold() # 实例化,不填参数默认方差0 x_var0 = selector.fit_transform(x) # 获取删除不合格特征后的新特征矩阵 x_var0.shape
默认方差阈值参数的情况下,过滤后还剩708个特征。
# 如果知道需要多少特征,找到特征方差的分位数作为阈值输入即可 import numpy as np x_fsvar = VarianceThreshold(np.median(x.var().values)).fit_transform(x) x_fsvar.shape
这是按方差取值的中位数为阈值,保留一半特征的情况。
# 基于方差过滤的结果来进一步做卡方过滤 from sklearn.ensemble import RandomForestClassifier as RFC from sklearn.model_selection import cross_val_score from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 x_fschi = SelectKBest(chi2,k=300).fit_transform(x_fsvar,y) x_fschi.shape
2.过滤法之卡方过滤,
卡方检验的本质是推测两组数据之间的差异,其检验的原假设是”两组数据是相互独立的”。卡方检验返回卡方值和P值两个统计量,其中卡方值很难界定有效的范围,而p值,我们一般使用0.01或0.05作为显著性水平,<=0.05或0.01表示两组数据相关,拒绝原假设。
使用sklearn中的chi2和SelectKBest选取指定个数的特征(k=300)。对比一下方差过滤和进一步卡方过滤的效果:
# 验证一下效果 print(cross_val_score(RFC(n_estimators=10,random_state=0),x_fsvar,y,cv=5).mean()) print(cross_val_score(RFC(n_estimators=10,random_state=0),x_fschi,y,cv=5).mean()) # 相关过滤后模型效果降低了,要么调大K值,要么放弃相关性过滤
对于卡方过滤中的超参数K值,用学习曲线查看K对模型的影响
# 选取超参数k,学习曲线 %matplotlib inline import matplotlib.pyplot as plt score = [] for i in range(390,220,-10): x_fschi = SelectKBest(chi2,k=i).fit_transform(x_fsvar,y) s = cross_val_score(RFC(n_estimators=10,random_state=0),x_fschi,y,cv=5).mean() score.append(s) plt.figure() plt.plot(range(390,220,-10), score) plt.show() # 随着保留特征数越多,模型效果越好。
实际运用中,学习曲线的方法耗时较长,也可以根据chi2获得各个特征对应的卡方值和p值,p值小于0.05时就能够拒绝特征与标签不相关的原假设,有95%的把握能够确定对应特征与标签相关。
# 获得各个特征对应的卡方值和p值 chivalue, pvalue_chi = chi2(x_fsvar,y) print(chivalue, pvalue_chi) # 可以看到p值都是0 # 现有数据集的特征都与标签相关,舍弃任何一个都可能舍弃对模型有用的信息。
#k取多少?我们想要消除所有p值大于设定值,比如0.05或0.01的特征: k = chivalue.shape[0] - (pvalue_chi > 0.05).sum() k
k=392说明方差过滤后的现有特征都与标签相关,保留。
3. 过滤法之F检验,用法类似于卡方过滤。方差齐性检验,是用来捕捉每个特征与标签之间的线性关系的过滤方法。它即可以做回归也可以做分类;F检验在数据服从正态分布时效果会非常稳定。F检验的本质是寻找两组数据之间的线性关系,其原假设是”数据不存在显著的线性关系“。它返回F值和p值两个统计量。
# F检验 from sklearn.feature_selection import f_classif F, pvalue_f = f_classif(x_fsvar,y) print(F) print(pvalue_f)
k = F.shape[0]-(pvalue_f>0.05).sum() k # 没有任何特征的p值大于0.01,所有特征都和标签相关,不需要F检验过滤。
4.过滤法之互信息法,用来捕捉每个特征与标签之间的任意关系(包括线性和非线性关系)的过滤方法,既可以做回归也可以做分类,不过互信息法比F检验更加强大,F检验只能够找出线性关系,而互信息法可以找出任意关系。返回“每个特征与目标之间的互信息量的估计”,这个估计量在[0,1]之间取值,为0则表示两个变量独立,为1则表示两个变量完全相关。
# 互信息法 from sklearn.feature_selection import mutual_info_classif as MIC result = MIC(x_fsvar,y) # result.shape k = result.shape[0]-sum(result<=0) k # 所有特征的互信息量估计都大于0,因此所有特征都与标签相关。
result>0表示特征与标签相关。
5.嵌入法,一种让算法自己决定使用哪些特征的方法,即特征选择和算法训练同时进行。依赖于算法自身的选择,比如coef_属性或feature_importances_属性来完成特征选择。
# 随机森林的嵌入法 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) x_embedded.shape # 指定阈值最终只剩下47个特征
学习曲线来确定属性选择中feature_importances_的阈值
# 画学习曲线 import numpy as np import matplotlib.pyplot as plt 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) s = cross_val_score(RFC_,x_embedded,y,cv=5).mean() score.append(s) plt.plot(threshold,score) plt.show()
根据图像可以再对阈值进行细分找到更优化的值。此处略过,只看结果。
x_embedded = SelectFromModel(RFC_,threshold=0.00055).fit_transform(x,y) x_embedded.shape print(cross_val_score(RFC_,x_embedded,y,cv=5).mean())
可以看到嵌入法直接把准确率提升到94%以上,相比方差过滤的
0.9388098166696807模型效果更好了。
6.包装法Wrapper
也是一个特征选择和算法训练同时进行的方法,与嵌入法十分相似,它也是依赖于算法自身的选择,比如coef_属性或feature_importances_属性来完成特征选择。包装法在初始特征集上训练评估器,并且通过coef_属性或通过feature_importances_属性获得每个特征的重要性。然后,从当前的一组特征中修剪最不重要的特征。在修剪的集合上递归地重复该过程,直到最终到达所需数量的要选择的特征。包装法要使用特征子集进行多次训练,因此它所需要的计算成本是最高的。但相比之下,包装法是最能保证模型效果的特征选择方法。
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() # 直接指定340个特征
support_:返回所有的特征的是否最后被选 中的布尔矩阵,以及.ranking_返回特征的按数次迭代中综合重要性的排名。
selector.ranking_
对包装法的选择特征个数画学习曲线
# 对包装法画学习曲线 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() # 应用50个特征时,模型的表现就已经达到了90%以上,比嵌入法和过滤法都高效很 # 多。我们可以放大图像,寻找模型变得非常稳定的点来画进一步的学习曲线
标签:RFC,机器,特征,过滤,feature,学习,score,import From: https://www.cnblogs.com/shi-yi/p/17084513.html