本篇講解一些特徵工程部分的特徵選擇(feature_selection),主要包括以下幾方面:

  • 特徵選擇是什麼
  • 為什麼要做特徵選擇
  • 特徵選擇的基本原則
  • 特徵選擇的方法及實現

特徵選擇是什麼

特徵選擇也稱特徵子集選擇,是從現有的m個特徵中選出對機器學習有用的n個特徵(n<=m),以此降低特徵維度減少計算量,同時也使模型效果達到最優。

為什麼要做特徵選擇

在實際業務中,用於模型中的特徵維度往往很高,幾萬維,有的一些CTR預估中維度高達上億維,維度過高會增大模型計算複雜度,但是在這麼多維數據中,並不是每個特徵對模型的預測都是有效果的,所以需要利用一些方法去除一些不必要特徵,從而降低模型的計算複雜度。

特徵選擇的基本原則

我們在進行特徵選擇時,主要遵循如下兩個原則:

  • 波動性
  • 相關性

波動性是指該特徵取值發生變化的情況,用方差來衡量,如果方差很小,說明該特徵的取值很穩定,可以近似理解成該特徵的每個值都接近,這樣的特徵對模型是沒有任何效果,是不具備區分度的,比如年齡這個特徵,都是20歲左右大小的。反之,方差越大,則特徵對模型的區分度越好。

相關性是就是該特徵和目標結果的相關性大小,常用皮爾遜相關係數來度量。

特徵選擇的方法及實現

1.移除低方差特徵

移除低方差特徵是指移除那些方差低於某個閾值,即特徵值變動幅度小於某個範圍的特徵,這一部分特徵的區分度較差,我們進行移除。

這裡的這個閾值需要根據具體的業務場景進行設定。

from sklearn.feature_selection import VarianceThreshold
X = [[0, 2, 1], [1, 1, 0], [2, 3, 0], [3, 6, 1], [4, 2, 0], [5, 1, 1]]
print(X)
print("---------------")
sel = VarianceThreshold(threshold=1)
sel.fit_transform(X)
print(sel.fit_transform(X))

2.單變數特徵選擇

單變數特徵是基於單一變數和目標y之間的關係,通過計算某個能夠度量特徵重要性的指標,然後選出重要性Top的K個特徵。但是這種方式有一個缺點就是忽略了特徵組合的情況,有的時候單一特徵可能表現不是很好,但是與其他特徵組合以後,效果就很不錯,這樣就會造成特徵被誤刪,所以這種特徵選擇方式不常用。該特徵選擇方式可以通過SelectKBest(score_func=<function f_classif at 0x6404aa0>, k=10)實現,其中score_func是用來指定特徵重要性的計算公式,k是特徵保留維度。下面是一些score_func函數及其解釋:

f_classif(相關性度量):

ANOVA F-value between label/feature for classification tasks.mutual_info_classif(互信息度量):

Mutual information for a discrete target.

chi2(卡方檢驗):Chi-squared stats of non-negative features for classification tasks.f_regression(用於回歸的相關性度量):F-value between label/feature for regression tasks.

mutual_info_regression(用於回歸的互信息度量):

Mutual information for a continuous target.SelectPercentile:Select features based on percentile of the highest scores.

SelectFpr:

Select features based on a false positive rate test.SelectFdr:Select features based on an estimated false discovery rate.SelectFwe:Select features based on family-wise error rate.GenericUnivariateSelect:Univariate feature selector with configurable mode.

遞歸式消除特徵

遞歸式消除特徵(RFE)是指,將全部特徵都丟到給定的模型裡面,模型會輸出每個特徵的重要性,然後刪除那些不太重要的特徵;把剩下的特徵再次丟到模型裡面,又會輸出各個特徵的重要性,再次刪除;如此循環,直至最後剩下目標維度的特徵值。

from sklearn.datasets import make_friedman1
from sklearn.feature_selection import RFE
from sklearn.svm import SVR
X, y = make_friedman1(n_samples=50, n_features=10, random_state=0)
estimator = SVR(kernel="linear")
##5個特徵被選中,每次迭代去除1個特徵。
selector = RFE(estimator, 5, step=1)
selector = selector.fit(X, y)
print(selector.support_) ##所選特徵的掩碼
##特徵排名,使得rank_ [i]對應於第i個特徵的排名位置。
##所選擇的(重要性最高的)特徵被分配為等級1,被刪除的特徵顯示其原始的位置。
selector.ranking_
print(selector.fit(X,y))

因為該方法每次都需要把特徵從新丟到模型裡面進行計算,計算量較為複雜;因該方法需要模型輸出特徵重要性,所以需要選用可以輸出特徵重要性的模型,比如LR的coef_。

使用SelectFromModel選取特徵

SelectFromModel可以用來處理任何帶有coef_或者feature_importances_ 屬性的訓練之後的模型。 如果相關的coef_ 或者 feature_importances 屬性值低於預先設置的閾值,這些特徵將會被認為不重要並且移除掉。除了指定數值上的閾值之外,還可以通過給定字元串參數來使用內置的啟發式方法找到一個合適的閾值。可以使用的啟發式方法有 mean 、 median 以及使用浮點數乘以這些(例如,0.1*mean )

SelectFromModel和遞歸式消除特徵不同的是,該方法不需要重複訓練模型,只需要訓練一次即可;二是該方法是指定權重的閾值,不是指定特徵的維度。

1.基於L1正則化的特徵提取

使用L1正則化的線性模型會得到一個稀疏權值矩陣,即生成一個稀疏模型:該模型的大多數係數為0,即特徵重要性為0,這個時候可以利用 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
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

2.基於Tree(樹)模型的特徵選取

我們知道樹模型的建立過程就是一個特徵選擇的過程,他會根據信息增益的準則來選擇信息增益最大的特徵來進行建模,輸出各個特徵的feature_importances_,然後傳入SelectFromModel進行特徵選擇。具體實現方式如下:

from sklearn.ensemble import ExtraTreesClassifier
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
iris = load_iris()
X, y = iris.data, iris.target
clf = ExtraTreesClassifier()
clf = clf.fit(X, y)
clf.feature_importances_
model = SelectFromModel(clf, prefit=True)
X_new = model.transform(X)
X_new.shape

推薦閱讀:

相關文章