Sklearn的feature_selection模塊中給出了其特征選擇的方法,實際工作中選擇特征的方式肯定不止這幾種的,IV,GBDT等等都ok;
一、移除低方差特征(Removing features with low variance)
API函數:sklearn.feature_selection.
VarianceThreshold
(threshold=0.0)
VarianceThreshold是特征選擇的一個簡單基本方法,它會移除所有那些方差不滿足一些閾值的特征。 在默認情況下,其會移除所有方差為0的特征,也就是所有取值相同的特征。
官網說:[
例如,假設我們有一個特征是布爾值的數據集,我們想要移除那些在整個數據集中特征值為0或者為1的比例超過80%的特征。布爾特征是伯努利( Bernoulli )隨機變量,變量的方差為
因此,我們可以使用閾值 ``.8 * (1 - .8)``進行選擇:
]
其用法可見,移除低於閾值的特征。但是對不不同的特征,其特征分布我們需要自己探索,即使對於離散特征數值化后或者連續特征,可以直接計算其方差。但是我認為這個選擇特征的方法實際意義有待商榷;對於一個特征取值唯一的情況,這種方法是肯定可以發現的。但是如果一個特征是布爾值,即使整個數據集合中有特征值為0或者為1的比例超過80%的特征,並不能說明這個特征不好哇,其對目標變量的相關性如果還不錯,你會忍心把這個變量剔除嗎。對吧,所以我實際工作中,沒用過這個方法。各抒己見!
二、單變量特征選擇,Univariate feature selection
這個有用,比上一個API有用多了。慢慢來看。
官網說【單變量的特征選擇是通過基於單變量的統計測試來選擇最好的特征。它可以當做是評估器的預處理步驟】。是的哇,單變量的特征選擇,出發點是想針對每一個特征單獨檢測其和目標變量Y的相關性,顧名思義單變量嘛。選擇方法很多,具體區分又區分,你所做的模型是回歸還是分類。
Scikit-learn 將特征選擇的內容作為實現了 transform 方法的對象
(1)、SelectKBest移除那些除了評分最高的 K 個特征之外的所有特征
(2)、SelectPercentile移除除了用戶指定的最高得分百分比之外的所有特征
這些對象將得分函數作為輸入,返回單變量的得分和 p 值:
- 對於回歸:
f_regression
,mutual_info_regression
- 對於分類:
chi2
,f_classif
,mutual_info_classif
可自行查看官網API文檔。
用例1,SelectPercentile的用法:
from sklearn.datasets import load_iris from sklearn.feature_selection import SelectKBest, SelectPercentile from sklearn.feature_selection import f_classif iris = load_iris() X, y = iris.data, iris.target sp = SelectPercentile(f_classif, percentile= 90) #得到返回至少含有90%特征信息的特征 X_result = sp.fit_transform(X, y) #可以看到哪些特征被保留 sp.get_support() #輸出結果 array([ True, False, True, True], dtype=bool)
用例2,依然使用iris數據集,看一下mutual_info_classif 和pandas中的corr()函數的信息相關性計算結果對比;
import pandas as pd from sklearn import datasets import numpy as np import seaborn as sns from sklearn.feature_selection import mutual_info_classif iris = datasets.load_iris() X = iris.data y = iris.target new_y = [y[i:i+1] for i in range(0, len(y), 1)] data = np.hstack((X, new_y)) data_df = pd.DataFrame(data) #0到3表示特征,4表示目標變量,畫圖查看相關性,如下圖所示 sns.heatmap(data_df.corr(), annot= True, fmt= '.2f')
0,1,2,3特征和4(目標變量)的相關性分別為【0.18,-0.42, 0.95,0.96】
互信息相關性:
mutual_info = mutual_info_classif(X, y, discrete_features= False) #輸出結果如下,和上面的結果對比看一下 array([ 0.48502046, 0.30654537, 0.99750059, 0.9849968 ])
三、遞歸特征消除(Recursive Feature Elimination)
官網解釋:給定一個外部的估計器,可以對特征賦予一定的權重(比如,線性模型的相關系數),recursive feature elimination ( RFE
) 通過考慮越來越小的特征集合來遞歸的選擇特征。 首先,評估器在初始的特征集合上面訓練並且每一個特征的重要程度是通過一個 coef_
屬性 或者 feature_importances_
屬性來獲得。 然后,從當前的特征集合中移除最不重要的特征。在特征集合上不斷的重復遞歸這個步驟,直到最終達到所需要的特征數量為止。
用例:
from sklearn.feature_selection import RFE from sklearn.ensemble import GradientBoostingClassifier from sklearn import datasets iris = datasets.load_iris() gbdt_RFE = RFE(estimator=GradientBoostingClassifier(random_state= 123),n_features_to_select=2) gbdt_RFE.fit(iris.data, iris.target) gbdt_RFE.support_ #特征選擇輸出結果 gbdt_RFE.support_ #輸出結果為: array([False, False, True, True], dtype=bool)
四、使用SelectFromModel 選取特征(Feature selection using SelectFromModel)
官網解釋:SelectFromModel是一個 meta-transformer(元轉換器) ,它可以用來處理任何帶有 coef_
或者 feature_importances_
屬性的訓練之后的評估器。 如果相關的``coef_`` 或者 featureimportances
屬性值低於預先設置的閾值,這些特征將會被認為不重要並且移除掉。除了指定數值上的閾值之外,還可以通過給定字符串參數來使用內置的啟發式方法找到一個合適的閾值。可以使用的啟發式方法有 mean 、 median 以及使用浮點數乘以這些(例如,0.1*mean )
4.1、基於 L1 的特征選取
用例:
from sklearn.svm import LinearSVC from sklearn.datasets import load_iris from sklearn.feature_selection import SelectFromModel iris = load_iris() X, y = iris.data, iris.target lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X, y) model = SelectFromModel(lsvc, prefit=True) X_new = model.transform(X) X_new.shape
4.2、基於 Tree(樹)的特征選取
基於樹的 estimators (查閱 sklearn.tree
模塊和樹的森林 在 sklearn.ensemble
模塊) 可以用來計算特征的重要性。
用例:
import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_classification from sklearn.ensemble import ExtraTreesClassifier # Build a classification task using 3 informative features X, y = make_classification(n_samples=1000, n_features=10, n_informative=3, n_redundant=0, n_repeated=0, n_classes=2, random_state=0, shuffle=False) # Build a forest and compute the feature importances forest = ExtraTreesClassifier(n_estimators=250, random_state=0) forest.fit(X,y) importances = forest.feature_importances_ indices = np.argsort(importances)[::-1] #作圖觀察特征重要性 plt.bar(range(10), importances[indices]) plt.xticks(range(X.shape[1]), indices) plt.show()
五、特征選取作為 pipeline(管道)的一部分(Feature selection as part of a pipeline)
官網解釋:
特征選擇通常在實際的學習之前用來做預處理。在 scikit-learn 中推薦的方式是使用 :sklearn.pipeline.Pipeline
:
clf = Pipeline([ ('feature_selection', SelectFromModel(LinearSVC(penalty="l1"))), ('classification', RandomForestClassifier()) ]) clf.fit(X, y)
在這段代碼中,我們利用 sklearn.svm.LinearSVC
和 sklearn.feature_selection.SelectFromModel
來評估特征的重要性並且選擇出相關的特征。 然后,在轉化后的輸出中使用一個 sklearn.ensemble.RandomForestClassifier
分類器,比如只使用相關的特征。你也可以使用其他特征選擇的方法和可以提供評估特征重要性的分類器來執行相似的操作。 請查閱 sklearn.pipeline.Pipeline
來了解更多的實例。