当前位置:   article > 正文

Python 三种方法对数据进行特征选择_python 特征选择方法

python 特征选择方法

关注微信公共号:小程在线

关注CSDN博客:程志伟的博客

特征选择:Filter过滤法、Embedded嵌入法、Wrapper包装法

特征选择选取高维度进行数据处理
##############特征选择 feature_selection#################
import pandas as pd
data = pd.read_csv(r"H:\程志伟\python\digit recognizor.csv")
X = data.iloc[:,1:]
y = data.iloc[:,0]
X.shape

Out[1]: (42000, 784)

############## 1 Filter过滤法 ###########
#####1.1 方差过滤
#优先消除方差为0的特征,方差为0表示该列的数据完全一致
from sklearn.feature_selection import VarianceThreshold
selector = VarianceThreshold() #实例化,不填参数默认方差为0
X_var0 = selector.fit_transform(X) #获取删除不合格特征之后的新特征矩阵
#也可以直接写成 X = VairanceThreshold().fit_transform(X)
X_var0.shape

Out[2]: (42000, 708)

 


#利用中位数删除
import numpy as np
np.median(X.var().values)

Out[3]: 1352.286703180131

 

#利用中位数进行变量的选择

X_fsvar = VarianceThreshold(np.median(X.var().values)).fit_transform(X)
X_fsvar.shape

Out[4]: (42000, 392)

 

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

Out[5]: (42000, 685)


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

KNN方差过滤前
#======【TIME WARNING:35mins +】======#
cross_val_score(KNN(),X,y,cv=5).mean()

准确率为:0.965856
#python中的魔法命令,可以直接使用%%timeit来计算运行这个cell中的代码所需的时间
#为了计算所需的时间,需要将这个cell中的代码运行很多次(通常是7次)后求平均值,因此运行%%timeit的时间会
#远远超过cell中的代码单独运行的时间
#======【TIME WARNING:4 hours】======#
%%timeit cross_val_score(KNN(),X,y,cv=5).mean()

KNN方差过滤后
#======【TIME WARNING:20 mins+】======#
cross_val_score(KNN(),X_fsvar,y,cv=5).mean()

准确率为:0.965999
#======【TIME WARNING:2 hours】======#
%%timeit
cross_val_score(KNN(),X,y,cv=5).mean()

 

随机森林方差过滤前
cross_val_score(RFC(n_estimators=10,random_state=0),X,y,cv=5).mean()

准确率为:0.938000

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


随机森林方差过滤后
cross_val_score(RFC(n_estimators=10,random_state=0),X_fsvar,y,cv=5).mean()

准确率为:0.938809

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


######################1.2 相关性过滤################
####1.2.1 卡方过滤不能计算负数
#卡方过滤是专门针对离散型标签(即分类问题)的相关性过滤
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
#假设在这里我一直我需要300个特征
X_fschi = SelectKBest(chi2, k=300).fit_transform(X_fsvar, y)
X_fschi.shape

Out[7]: (42000, 300)

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

Out[8]: 0.9333098667649198


####1.2.2 选取超参数K
%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()


从P得出K值
#从特征工程的角度,我们希望选取卡方值很大,p值小于0.05的特征
chivalue, pvalues_chi = chi2(X_fsvar,y)
chivalue
pvalues_chi


#k取多少?我们想要消除所有p值大于设定值,比如0.05或0.01的特征:
k = chivalue.shape[0] - (pvalues_chi > 0.05).sum()

Out[12]: 392
#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()

 

####1.2.3 F检验又称ANOVA,方差齐性检验

#我们希望选取p值小于0.05或0.01的特征,这些特征与标签时显著线性相关的
from sklearn.feature_selection import f_classif
F, pvalues_f = f_classif(X_fsvar,y)
F
pvalues_f
k = F.shape[0] - (pvalues_f > 0.05).sum()
k

Out[13]: 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()

 

 

##1.2.4 互信息法

#互信息法不返回p值或F值类似的统计量,它返回“每个特征与目标之间的互信息量的估计”,这个估计量在[0,1]之间
取值,为0则表示两个变量独立,为1则表示两个变量完全相关
from sklearn.feature_selection import mutual_info_classif as MIC
result = MIC(X_fsvar,y)
k = result.shape[0] - sum(result <= 0)
k

Out[14]: 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()


####3.2 Embedded嵌入法

在使用嵌入法时,我们先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据权值系数从大到小选择特征。这些权值系数往往代表了特征对于模型的某种贡献或某种重要性


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_
X_embedded.shape

Out[15]: (42000, 47)
#模型的维度明显被降低了
#同样的,我们也可以画学习曲线来找最佳阈值


#======【TIME WARNING:10 mins】======#
import numpy as np
import matplotlib.pyplot as plt
RFC_.fit(X,y).feature_importances_
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()

X_embedded = SelectFromModel(RFC_,threshold=0.00067).fit_transform(X,y)
X_embedded.shape

Out[17]: (42000, 324)


cross_val_score(RFC_,X_embedded,y,cv=5).mean()

Out[18]: 0.939905083368037

特征个数瞬间缩小到324多,这比我们在方差过滤的时候选择中位数过滤出来的结果392列要小,并且
交叉验证分数0.9399高于方差过滤后的结果0.9388,这是由于嵌入法比方差过滤更具体到模型的表现的缘故

 

#======【TIME WARNING:10 mins】======#
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)
X_embedded.shape

Out[20]: (42000, 340)


cross_val_score(RFC_,X_embedded,y,cv=5).mean()

Out[22]: 0.9408335415056387


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

Out[23]: 0.9639525817795566


###########3.3 Wrapper包装法##############

它是一种贪婪的优化算法,旨在找到性能最佳的特征子集。 它反复创建模型,并在每次迭代时保留最佳特征或剔除最差特征,下一次迭代时,它会使用上一次建模中没有被选中的特征来构建下一个模型,直到所有特征都耗尽为止。参数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()

Out[25]: 340


selector.ranking_

array([10,  9,  8,  7,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
        6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  7,  7,  6,  6,
        ......
        8,  7,  8,  8,  8,  7,  8,  8,  8,  8,  8,  7,  8,  8,  8,  8,  9,
       10,  7])


X_wrapper = selector.transform(X)
cross_val_score(RFC_,X_wrapper,y,cv=5).mean()

Out[29]: 0.9389522459432109


#======【TIME WARNING: 15 mins】======#
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%以上,比嵌入法和过滤法都高效很多。

 

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

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/140952
推荐阅读
相关标签
  

闽ICP备14008679号