特征提取——特征创造——特征选择
一、过滤法
(1)方差过滤
特征本身的方差很小,就表示样本在这个特征上基本没有差异,可能特征中的大多数指都一样,那么这个特征对于样本区分没有什么作用。所以,优先消除方差为0的特征。
注意:方差过滤对随机森林影响不大,因为随机森林本来就是随机选取特征进行分枝,本身运算就非常快速,因此特征选择对它来说效果不明显。
data_x = newframe.iloc[:,newframe.columns != "vote_average"]
data_y = (newframe.loc[:,"vote_average"])
print("data_x:{}".format(data_x.shape)) #输出:data_x:(1000, 24125)
print("data_y:{}".format(data_y.shape)) #输出:data_y:(1000,)
from sklearn.feature_selection import VarianceThreshold #导入方差过滤的包
selector = VarianceThreshold() # 实例化,不填参数默认方差为0
X = selector.fit_transform(data_x) # 获取删除不合格特征之后的新特征矩阵
# 也可以直接写成 X = VairanceThreshold().fit_transform(data_x)
print("X:{}".format(X.shape)) #输出:X:(1000, 1022),特征减少到1022个
(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
X_fschi = SelectKBest(chi2, k=300).fit_transform(data_x, y) #假设在这里我一直我需要300个特征
X_fschi.shape
超参数K的选取:(学习曲线)
import matplotlib.pyplot as plt
score = []
for i in range(390,200,-10):
X_fschi = SelectKBest(chi2, k=i).fit_transform(data_x, y)
once = cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()
score.append(once)
plt.plot(range(350,200,-10),score)
plt.show()
2、F检验
用来捕捉每个特征与标签之间的线性的过滤方法。既可以回归又可以做分类。
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 f_classif
X_f_classif = SelectKBest(f_classif, k=300).fit_transform(data_x, y) #假设在这里我一直我需要300个特征
X_f_classif.shape
3、互信息法
用来捕捉每个特征与标签之间的任意关系(包括线性和非线性关系)的过滤方法。既可以回归又可以做分类。
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 mutual_info_classif as MIC
X_f_classif = SelectKBest(MIC, k=300).fit_transform(data_x, y) #假设在这里我一直我需要300个特征
X_f_classif.shape
二、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这个阈值是非常高的阈值,因为平均每个特征只能够分到大约0.001的feature_importances_
X_embedded.shape
#模型的维度明显被降低了
#画学习曲线来找最佳阈值
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()
三、Wrapper包装法
也是依赖于自身的选择。包装法在初始特征集上训练评估器,并通过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() #.support_:返回所有的特征是否最后被选中的布尔矩阵
selector.ranking_ #返回特征的按数次迭代中综合重要性的排名
X_wrapper = selector.transform(X)
cross_val_score(RFC_,X_wrapper,y,cv=5).mean()
四、总结
过滤法更快速,但更粗糙。
包装法和嵌入法更精确,比较适合具体到算法去调整,但计算量较大,运行时间长。
当数据量很大的时候,优先使用方差过滤和互信息法调整,再上其他特征选择方法。
使用逻辑回归时,优先使用嵌入法;使用支持向量机时,优先使用包装法。