特征选择
特征選擇
特征選擇是從數(shù)據(jù)集的諸多特征里面選擇和目標(biāo)變量相關(guān)的特征,去掉那些不相關(guān)的特征。
特征選擇分為兩個問題:一個是子集搜索問題,另外一個是子集評價問題。比如將前向搜索和信息熵評價這兩種策略進(jìn)行結(jié)合就是決策樹算法,事實上決策樹算法可以進(jìn)行特征選擇。sklearn當(dāng)中的“樹形”算法的feature_importances_就是特征重要性的體現(xiàn)。
常用的特征選擇分為三類:過濾式(filter),包裹式(wrapper)和嵌入式(embedding)
過濾式: 先進(jìn)行特征選擇,然后進(jìn)行后續(xù)的訓(xùn)練,特征選擇和后續(xù)的訓(xùn)練過程沒有關(guān)系。
包裹式: 將機器學(xué)習(xí)的性能當(dāng)做子集評價標(biāo)準(zhǔn)。
嵌入式: 將特征選擇和機器學(xué)習(xí)融為一體,兩者在同一個優(yōu)化過程當(dāng)中完成。和包裹式學(xué)習(xí)不同的是,包裹式中的子集選擇和機器訓(xùn)練過程還是有區(qū)分的,而嵌入式將這兩個過程融為一個過程。
sklearn當(dāng)中的特征選擇
1:移除方差較低的特征 VarianceThreshold方法
移除方差比較低的特征,使用方差作為特征選擇的一個標(biāo)準(zhǔn),是因為觀察到這么一個事實,方差較低的樣本差異不大,對我們的目標(biāo)變量貢獻(xiàn)比較低,所以我們移除方差比較低的樣本。
舉個例子,假如特征是boolean類型,那么它是伯努利隨機變量,它的方差為$D(X) = p(1-p)$。 假如我們想要移除特征當(dāng)中有超過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))
輸出結(jié)果如下,可以看到把第一列給移除了:
[[0 1] [1 0] [0 0] [1 1] [1 0] [1 1]]
使用variances_ 屬性可以獲得各個特征的方差:
print(clf.variances_)
[0.13888889 0.22222222 0.25 ]
注意:這里的VarianceThreshold和我們傳統(tǒng)意義上面的anova(analysis of variance)沒有關(guān)系。這里的VarianceThreshold方法不依賴于類的取值,只和特征本身的方差有關(guān),所以可以用在無監(jiān)督學(xué)習(xí)當(dāng)中。而單因素的anova的傳統(tǒng)應(yīng)用是觀察一組因素是否對我們的試驗指標(biāo)有顯著的影響。下面的f_classif則是利用anova的原理。
2:單變量特征選擇
利用統(tǒng)計學(xué)當(dāng)中的方差假設(shè)檢驗的知識來對模型的特征進(jìn)行選擇,我在特征相似性度量中介紹了一下這些方法。
其中SelectKBest是用來選擇k個最高分?jǐn)?shù)的特征,SelectPercentile是選擇百分比個分?jǐn)?shù)最高的特征
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)
結(jié)果如下:
(150, 4) (150, 2)
上面選用的是$chi^2$測試,
其它的還有:對于回歸問題:f_regression, mutual_info_regression 。對于分類問題有: chi2, f_classif, mutual_info_classif。
事實上在統(tǒng)計學(xué)當(dāng)中使用的測試的結(jié)果,比如$chi^2$值,還有F值等都可以轉(zhuǎn)化為p值。所以SelectKBest有兩種方法可以查看特征的狀況,一個是scores_屬性,另外一個是pvalues_屬性。
k_best = SelectKBest(chi2, k=2).fit(X, y) print(k_best.scores_) print(k_best.pvalues_)
可以得到如下結(jié)果:
[ 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) 是使用回歸的方法,在一個模型里面不斷的減少不重要的特征,最后達(dá)到我們要的特征。下面是RFE中的參數(shù):
estimator:輸入需要的模型。
n_features_to_select:需要選擇的特征,默認(rèn)選擇半數(shù)。
step:如果大于等于1,那么每次迭代的時候去除step個,如果是0到1之間的小數(shù),代表每次迭代去除的百分比。
下面是在手寫數(shù)字識別數(shù)據(jù)集當(dāng)中進(jìn)行像素選擇的例子:
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()
輸出結(jié)果如下:
還有一個方法是RFECV,是將回歸特征消除和交叉驗證結(jié)合在一起了。 那么它和RFE有什么不同哪?RFE是使用模型當(dāng)中的coef_或者feature_importances_這兩個屬性來評價特征的好壞,前者是線性模型的特征相關(guān)系數(shù),后者是樹模型的重要性。而RFECV是使用交叉驗證來評估特征對模型的好壞,可以傳入自己的評分函數(shù)。
RFE和RFECV中重要參數(shù)
在使用RFE和RFECV的時候,有一些參數(shù)是非常重要的,參考這個博客,以selector表示我們RFE或者RFECV fit以后的模型。
selector.n_features_ :選擇的特征數(shù)量
selector.support_ : 特征是否選擇,返回的是n個特征的ture或者false的列表,和selector.get_support()相等
selector.ranking_ : 特征的重要排名程度
selector.grid_scores : 特征的分?jǐn)?shù)
使用SelectFromModel來對特征進(jìn)行選擇
SelectFromModel使用了core_和feature_importances_,前者在線性模型當(dāng)中使用,后者在樹模型當(dāng)中使用。
4:基于L1正則化的特征選擇(線性模型的特征選擇)。
線性模型使用L1正則化作為罰函數(shù),在這種情況下系數(shù)當(dāng)中有很多是0,這些為0的系數(shù)是不重要的系數(shù),可以去掉,這就起到了特征選擇的作用。它可以和SelectFromModel一起結(jié)合使用。
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)
結(jié)果如下:
(150, 4) (150, 3)
線性模型的coef_屬性,返回的是每個特征分配的權(quán)重(也就是相關(guān)系數(shù)),如果n_classes=2,那么返回的是[n_features]的大小,否則返回[n_classes,n_features]的大小。
print(lsvc.coef_)
結(jié)果如下:
[[ 0. 0.21680093 -0.28727284 0. ] [ 0. -0.09186784 0. 0. ] [-0.03499577 -0.17024796 0.13484725 0. ]]
5:基于樹結(jié)構(gòu)的特征選擇:
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)
結(jié)果如下:
[0.09666543 0.06817362 0.50460169 0.33055925] (150, 4) (150, 2)
總結(jié)一下:
第一種方法和第二種方法都屬于過濾式,前者利用方差信息,后者利用統(tǒng)計學(xué)中的單變量統(tǒng)計測試方法進(jìn)行特征選擇,特征的選擇和后續(xù)的訓(xùn)練沒有關(guān)系。 第三種方法RFE以及RFECV屬于包裹式,使用遞歸的方法進(jìn)行特征選擇,使用模型的結(jié)果來進(jìn)行特征評估。第四種和第五種方法分別講了利用線性模型和樹模型進(jìn)行特征選擇的過程,屬于嵌入式。 嵌入式和包裹式的不同從上面的算法當(dāng)中也可以看出來,嵌入式將模型選擇和機器學(xué)習(xí)看做一個優(yōu)化過程,而包裹式則是利用模型的性能當(dāng)做特征的評價標(biāo)準(zhǔn)。
參考:
Feature selection 這是sklearn的官方文檔介紹的feature selection 方法
周志華 《機器學(xué)習(xí)》
總結(jié)
- 上一篇: 腾讯代理,育碧 3A 射击游戏《全境封锁
- 下一篇: 为SAP UI5正名 - 它也支持双向绑