【sklearn】特征選擇和降維


1.13 特征選擇

sklearn.feature_selection模塊中的類可以用於樣本集上的特征選擇/降維,以提高估計器的精度值,或提高其應用在高維數據集上的性能。

1.13.1 刪除低方差的特征

VarianceThreshold是一種簡單的特征選擇baseline方法。它刪除了方差不滿足某個閾值的所有特性。
默認情況下,它會刪除所有的零方差特性,即在所有樣本中具有相同值的特性。

例如,假設我們有一個具有布爾特征的數據集,並且我們想要刪除超過80%的樣本中所有要么為1要么為0(開或關)的特征。
布爾特征是伯努利隨機變量,其方差為

\(\mathrm{Var}[X] = p(1 - p)\)

所以我們可以選擇使用閾值 .8 * (1 - .8):

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]]

sel = VarianceThreshold(threshold=(.8 * (1 - .8)))
sel.fit_transform(X)

array([[0, 1],
[1, 0],
[0, 0],
[1, 1],
[1, 0],
[1, 1]])

VarianceThreshold刪除了第一列,該列包含0的概率為p = 5/6 > .8。

1.13.2 單變量特征選擇

單變量特征選擇的工作原理是基於單變量統計檢驗來選擇最佳特征。它可以被看作是估計器的一個預處理步驟。
Scikit-learn將特性選擇例程作為實現轉換方法的對象公開:

  • SelectKBest 刪除了k個最高評分的特征以外的所有特性;

  • SelectPercentile 刪除了除用戶指定的最高評分百分比以外的所有特征;

  • 對每個特征使用常見的單變量統計檢驗: 假陽性率SelectFpr,假發現率SelectFdr,或族判斷誤差率SelectFwe;

  • GenericUnivariateSelect允許使用可配置策略執行單變量特性選擇。這允許選擇最好的單變量選擇策略與超參數搜索估計器。

例如,我們可以對樣本進行\(\chi^2\)測試,只檢索兩個最好的特征:

from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

X, y = load_iris(return_X_y=True)
X_new = SelectKBest(chi2, k=2).fit_transform(X, y)

X.shape, X_new.shape

((150, 4), (150, 2))

這些對象接受一個評分函數作為輸入,該函數返回單變量分數和p-值(或僅返回SelectKBest和SelectPercentile的分數):

對於回歸問題: f_regression, mutual_info_regression

對於分類問題: chi2, f_classif, mutual_info_classif

基於F檢驗的方法估計了兩個隨機變量之間的線性相關程度。
另一方面,互信息方法可以捕獲任何類型的統計相關性,但由於是非參數的,因此需要更多的樣本來進行准確的估計。

1.13.3 遞歸特征刪除

給定一個給特征賦予權重的外部估計量(例如,線性模型的系數),遞歸特征刪除(RFE)是通過遞歸地考慮越來越小的特征集來選擇特征。
首先,對估計器進行原始特征集的訓練,然后通過coef_屬性或feature_importances_屬性獲得每個特征的重要性。
然后,從當前的一組特性中刪除最不重要的特性。該過程在修剪集上遞歸地重復,直到最終達到所需的要選擇的特性數量。

RFECV在交叉驗證循環中執行RFE,以找到最優的特性數量。

1.13.4 用SelectFromModel選擇特征

SelectFromModel是一個元轉換器,可以與任何在擬合后具有coef_或feature_importances_屬性的估計器一起使用。
如果相應的coef_或feature_importances_值低於提供的閾值參數,則認為這些特性不重要並將其刪除。
除了以數字方式指定閾值外,還有使用字符串參數查找閾值的內置啟發式方法。
可用的啟發式方法是“平均數”、“中位數”和這些數的浮點倍數,如“0.1*平均數”。

有關如何使用它的示例,請參考下面的部分。

1.13.4.1 基於L1的特征選擇

用L1范數懲罰的線性模型具有稀疏解:它們的許多估計系數為零。
當目標是減少與另一個分類器一起使用的數據的維數時,可以將它們與feature_selection.SelectFromModel一起使用來選擇非零系數。
特別是,稀疏估計器很適用此場景,如用於回歸的linear_model.Lasso和用於分類的linear_model.LogisticRegression和svm.LinearSVC:

from sklearn.svm import LinearSVC
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel

X, y = load_iris(return_X_y=True)
lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X, y)
model = SelectFromModel(lsvc, prefit=True)
X_new = model.transform(X)
X.shape, X_new.shape

((150, 4), (150, 3))

對於支持向量機和邏輯回歸,參數C控制了稀疏性:C越小,選擇的特征越少。對於Lasso, alpha參數越高,選擇的特征越少。

1.13.4.2 基於樹的特征選擇

基於樹的估計器(參照sklearn.tree模塊和sklearn.ensemble模塊中的森林)可用於計算特征的重要性,而這些重要性又可用於丟棄不相關的特征(與SelectFromModel元轉換器結合使用):

from sklearn.ensemble import ExtraTreesClassifier
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel

X, y = load_iris(return_X_y=True)
clf = ExtraTreesClassifier(n_estimators=50)
clf = clf.fit(X, y)

model = SelectFromModel(clf, prefit=True)
X_new = model.transform(X)
X.shape, X_new.shape, clf.feature_importances_

((150, 4), (150, 2), array([0.09394361, 0.05591118, 0.42796637, 0.42217885]))

1.13.5 特征選擇作為流水線的一部分

特征選擇通常用作實際學習之前的預處理步驟。在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針對轉換后的輸出進行訓練,即僅使用相關特征。
還可以使用其他特性選擇方法以及提供評估特性重要性方法的分類器執行類似的操作。

完整案例

一個顯示單變量特征選擇的例子。

在iris數據中加入噪聲(非信息性)特征,應用單變量特征選擇。
對於每個特征,我們繪制單變量特征選擇的p值和支持向量機相應的權值。
我們可以看到,單變量特征選擇選擇了信息特征,並且這些特征具有更大的SVM權值。

在整個特征集中,只有前四個特征是重要的。我們可以看到他們在單變量特征選擇上得分最高。
支持向量機給這些特征賦予了很大的權重,但也選擇了許多非信息性特征。
在支持向量機之前進行單變量特征選擇,可以增加支持向量機的顯著特征權重,從而改善分類。

print(__doc__)

import numpy as np
import matplotlib.pyplot as plt

from sklearn import datasets, svm
from sklearn.feature_selection import SelectPercentile, f_classif

# #############################################################################
# Import some data to play with

# The iris dataset
iris = datasets.load_iris()

# Some noisy data not correlated
E = np.random.uniform(0, 0.1, size=(len(iris.data), 20))

# Add the noisy data to the informative features
X = np.hstack((iris.data, E))
y = iris.target

plt.figure(1)
plt.clf()

X_indices = np.arange(X.shape[-1])

# #############################################################################
# Univariate feature selection with F-test for feature scoring
# We use the default selection function: the 10% most significant features
selector = SelectPercentile(f_classif, percentile=10)
selector.fit(X, y)
scores = -np.log10(selector.pvalues_)
scores /= scores.max()
plt.bar(X_indices - .45, scores, width=.2,
        label=r'Univariate score ($-Log(p_{value})$)', color='darkorange',
        edgecolor='black')

# #############################################################################
# Compare to the weights of an SVM
clf = svm.SVC(kernel='linear')
clf.fit(X, y)

svm_weights = (clf.coef_ ** 2).sum(axis=0)
svm_weights /= svm_weights.max()

plt.bar(X_indices - .25, svm_weights, width=.2, label='SVM weight',
        color='navy', edgecolor='black')

clf_selected = svm.SVC(kernel='linear')
clf_selected.fit(selector.transform(X), y)

svm_weights_selected = (clf_selected.coef_ ** 2).sum(axis=0)
svm_weights_selected /= svm_weights_selected.max()

plt.bar(X_indices[selector.get_support()] - .05, svm_weights_selected,
        width=.2, label='SVM weights after selection', color='c',
        edgecolor='black')


plt.title("Comparing feature selection")
plt.xlabel('Feature number')
plt.yticks(())
plt.axis('tight')
plt.legend(loc='upper right')
plt.show()

Automatically created module for IPython interactive environment

參考資料

sklearn user guide 1.13 Feature secection


免責聲明!

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



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