特征選擇
特征選擇
特征選擇是從數據集的諸多特征裏面選擇和目標變量相關的特征,去掉那些不相關的特征。
特征選擇分為兩個問題:一個是子集搜索問題,另外一個是子集評價問題。比如將前向搜索和信息熵評價這兩種策略進行結合就是決策樹算法,事實上決策樹算法可以進行特征選擇。sklearn當中的“樹形”算法的feature_importances_就是特征重要性的體現。
常用的特征選擇分為三類:過濾式(filter),包裹式(wrapper)和嵌入式(embedding)
過濾式: 先進行特征選擇,然後進行後續的訓練,特征選擇和後續的訓練過程沒有關系。
包裹式: 將機器學習的性能當做子集評價標準。
嵌入式: 將特征選擇和機器學習融為一體,兩者在同一個優化過程當中完成。和包裹式學習不同的是,包裹式中的子集選擇和機器訓練過程還是有區分的,而嵌入式將這兩個過程融為一個過程。
sklearn當中的特征選擇
1:移除方差較低的特征 VarianceThreshold方法
移除方差比較低的特征,使用方差作為特征選擇的一個標準,是因為觀察到這麽一個事實,方差較低的樣本差異不大,對我們的目標變量貢獻比較低,所以我們移除方差比較低的樣本。
舉個例子,假如特征是boolean類型,那麽它是伯努利隨機變量,它的方差為$D(X) = p(1-p)$。 假如我們想要移除特征當中有超過80%要麽是0要麽是1的樣本,那麽我們把方差的閾值定義為 0.8*(1-0.8)=0.16
from sklearn.feature_selection import VarianceThreshold X = [[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1, 1]] #樣本為: ‘‘‘ 0 0 1 0 1 0 0 1 1 0 1 0 0 1 1 ‘‘‘ clf = VarianceThreshold(threshold=(0.8 * (1-0.8))) print(clf.fit_transform(X))
輸出結果如下,可以看到把第一列給移除了:
[[0 1] [1 0] [0 0] [1 1] [1 0] [1 1]]
2:單變量特征選擇
利用統計學當中的方差假設檢驗的知識來對模型的特征進行選擇,
其中SelectKBest是用來選擇k個最高分數的特征,SelectPercentile是選擇百分比個分數最高的特征
from sklearn.datasets import load_iris from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 iris = load_iris() X, y = iris.data, iris.target print(X.shape) X_new = SelectKBest(chi2, k=2).fit_transform(X, y) print(X_new.shape)
結果如下:
(150, 4)
(150, 2)
上面選用的是$\chi^2$測試,
其它的還有:對於回歸問題:f_regression, mutual_info_regression 。對於分類問題有: chi2, f_classif, mutual_info_classif
3: 回歸特征消除
Recursive feature elimination(RFE) 是使用回歸的方法,在一個模型裏面不斷的減少不重要的特征,最後達到我們要的特征。下面是RFE中的參數:
estimator:輸入需要的模型。
n_features_to_select:需要選擇的特征,默認選擇半數。
step:如果大於等於1,那麽每次叠代的時候去除step個,如果是0到1之間的小數,代表每次叠代去除的百分比。
下面是在手寫數字識別數據集當中進行像素選擇的例子:
from sklearn.datasets import load_digits from sklearn.svm import SVC from sklearn.feature_selection import RFE import matplotlib.pyplot as plt digits = load_digits() X = digits.images.reshape((len(digits.images), -1)) y = digits.target svc = SVC(kernel=‘linear‘, C=1) rfe = RFE(svc, n_features_to_select=1, step=1) rfe.fit(X, y) ranking = rfe.ranking_.reshape(digits.images[0].shape) plt.matshow(ranking, cmap=plt.cm.Blues) plt.colorbar() plt.title("Ranking of pixels with RFE") plt.show()
輸出結果如下:
還有一個方法是RFECV,是將回歸特征消除和交叉驗證結合在一起了。 那麽它和RFE有什麽不同哪?RFE是使用模型當中的coef_或者feature_importances_這兩個屬性來評價特征的好壞,前者是線性模型的特征相關系數,後者是樹模型的重要性。而RFECV是使用交叉驗證來評估特征對模型的好壞,可以傳入自己的評分函數。
使用SelectFromModel來對特征進行選擇
SelectFromModel使用了core_和feature_importances_,前者在線性模型當中使用,後者在樹模型當中使用。
4:基於L1正則化的特征選擇。
線性模型使用L1正則化作為罰函數,在這種情況下系數當中有很多是0,這些為0的系數是不重要的系數,可以去掉,這就起到了特征選擇的作用。它可以和SelectFromModel一起結合使用。
from sklearn.datasets import load_iris
from sklearn.svm import LinearSVC
from sklearn.feature_selection import SelectFromModel
iris = load_iris()
X, y = iris.data, iris.target
print(X.shape)
lsvc = LinearSVC(C=0.01, penalty=‘l1‘, dual=False).fit(X, y)
model = SelectFromModel(lsvc, prefit=True)
X_new = model.transform(X)
print(X_new.shape)
結果如下:
(150, 4)
(150, 3)
5:基於樹結構的特征選擇:
from sklearn.datasets import load_iris from sklearn.ensemble import ExtraTreesClassifier from sklearn.feature_selection import SelectFromModel iris = load_iris() X, y = iris.data, iris.target clf = ExtraTreesClassifier() clf = clf.fit(X, y) print(clf.feature_importances_) print(X.shape) model = SelectFromModel(clf, prefit=True) X_new = model.transform(X) print(X_new.shape)
結果如下:
[0.09666543 0.06817362 0.50460169 0.33055925] (150, 4) (150, 2)
總結一下:
第一種方法和第二種方法都屬於過濾式,前者利用方差信息,後者利用統計學中的單變量統計測試方法進行特征選擇,特征的選擇和後續的訓練沒有關系。 第三種方法RFE以及RFECV屬於包裹式,使用遞歸的方法進行特征選擇,使用模型的結果來進行特征評估。第四種和第五種方法分別講了利用線性模型和樹模型進行特征選擇的過程,屬於嵌入式。 嵌入式和包裹式的不同從上面的算法當中也可以看出來,嵌入式將模型選擇和機器學習看做一個優化過程,而包裹式則是利用模型的性能當做特征的評價標準。
參考:
Feature selection
周誌華 《機器學習》
特征選擇