特征選擇


特征選擇

特征選擇是從數據集的諸多特征里面選擇和目標變量相關的特征,去掉那些不相關的特征。

特征選擇分為兩個問題:一個是子集搜索問題,另外一個是子集評價問題。比如將前向搜索和信息熵評價這兩種策略進行結合就是決策樹算法,事實上決策樹算法可以進行特征選擇。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]]

使用variances_ 屬性可以獲得各個特征的方差:

print(clf.variances_)
[0.13888889 0.22222222 0.25      ]

 

注意:這里的VarianceThreshold和我們傳統意義上面的anova(analysis of variance)沒有關系。這里的VarianceThreshold方法不依賴於類的取值,只和特征本身的方差有關,所以可以用在無監督學習當中。而單因素的anova的傳統應用是觀察一組因素是否對我們的試驗指標有顯著的影響。下面的f_classif則是利用anova的原理。

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。

  事實上在統計學當中使用的測試的結果,比如$chi^2$值,還有F值等都可以轉化為p值。所以SelectKBest有兩種方法可以查看特征的狀況,一個是scores_屬性,另外一個是pvalues_屬性。

k_best = SelectKBest(chi2, k=2).fit(X, y)
print(k_best.scores_)
print(k_best.pvalues_)

可以得到如下結果:

[ 10.81782088   3.59449902 116.16984746  67.24482759]
[4.47651499e-03 1.65754167e-01 5.94344354e-26 2.50017968e-15]

 

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

輸出結果如下:

Figure_1

還有一個方法是RFECV,是將回歸特征消除和交叉驗證結合在一起了。 那么它和RFE有什么不同哪?RFE是使用模型當中的coef_或者feature_importances_這兩個屬性來評價特征的好壞,前者是線性模型的特征相關系數,后者是樹模型的重要性。而RFECV是使用交叉驗證來評估特征對模型的好壞,可以傳入自己的評分函數。

RFE和RFECV中重要參數

在使用RFE和RFECV的時候,有一些參數是非常重要的,參考這個博客,以selector表示我們RFE或者RFECV fit以后的模型。

selector.n_features_   :選擇的特征數量

selector.support_  : 特征是否選擇,返回的是n個特征的ture或者false的列表,和selector.get_support()相等

selector.ranking_  :   特征的重要排名程度

selector.grid_scores  : 特征的分數

 

使用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)
線性模型的coef_屬性,返回的是每個特征分配的權重(也就是相關系數),如果n_classes=2,那么返回的是[n_features]的大小,否則返回[n_classes,n_features]的大小。
print(lsvc.coef_)

  結果如下:

[[ 0.          0.21680093 -0.28727284  0.        ]
 [ 0.         -0.09186784  0.          0.        ]
 [-0.03499577 -0.17024796  0.13484725  0.        ]]

 

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   這是sklearn的官方文檔介紹的feature selection 方法

周志華 《機器學習》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM