特徵工程: 特徵, 特徵提取和特徵選擇

機器學習中的特徵

在機器學習和模式識別中,特徵是在觀測現象中的一種獨立、可測量的屬性。選擇信息量大的、有差別性的、獨立的特徵是模式識別、分類和迴歸問題的關鍵一步。
最初的原始特徵數據集可能太大,或者信息冗餘,因此在機器學習的應用中,一個初始步驟就是選擇特徵的子集,或構建一套新的特徵集,減少功能來促進算法的學習,提高泛化能力和可解釋性。
在機器視覺中,一幅圖像是一個觀測,但是特徵可能是圖中的一條線;在自然語言處理中,一個文本是一個觀測,但是其中的段落或者詞頻可能纔是一種特徵;在語音識別中,一段語音是一個觀測,但是一個詞或者音素纔是一種特徵。

特徵的重要性

在特徵選擇時, 經常根據重要性, 將重要的特徵選擇出來放入訓練集合. 相關係數和獨立變量方法是常用的方法。
在構建模型的過程中, 有時候也會用到一些複雜的預測模型進行特徵的重要性評價和選擇, 例如多元自適應迴歸樣條法( Multivariate Adaptive Regression Splines, MARS), 隨機森林( Random Forest), 梯度提升機( Gradient Boosted Machines)等.

特徵提取和特徵選擇

  • 特徵提取
    對原始觀測進行降維以便於建模的過程, 對於表格式的數據, 可以用主成分分析PCA, 聚類等方法; 對於圖像數據, 可以用線(line)/邊緣(edge)提取, 對於視頻, 音頻數據, 很多數字信號處理的方法都可以用於特徵提取.
  • 特徵選擇
    特徵選擇是自動地選擇出對於問題最重要的特徵子集的過程. 由於不同特徵對模型準確度的影響程度不同, 特徵選擇算法用評分排序, 或者用反覆實驗來搜索出特徵子集, 自動創建並評估模型得到最佳特徵子集. 另外還有一些方法將特徵選擇作爲模型的附加功能, 例如逐步迴歸法( stepwise regression)
    sklearn的feature_selection模塊在特徵選擇和樣本集合降維上, 用來提高模型的正確率或者提高他們在高維度數據上的表現.

特徵選擇的方法可以大致分爲:

  1. Filter: 過濾法, 按照方差或者相關性對特徵評分, 根據閾值選擇特徵
  2. Wrapper: 包裝法, 根據目標函數(預測效果評分), 選擇/排除若干特徵

特徵選擇的目的:

  1. 降維, 增強模型泛化能力, 減少過擬合
  2. 便於理解特徵和標籤之間的關係

去除方差較小的特徵

VarianceThreshold是一個簡單的特徵選擇基準方法, 該方法就是去除所有沒有達到指定閾值的特徵. 默認是去除所有零方差的數據, 例如那些在所有樣本中都一樣的特徵.

舉例來說, 我們有一個數據集合, 所有的數據都是布爾值, 我們想去掉80%的概率上不是0就是1的特徵維度, 對於布爾型的數據來說, 服從伯努利分佈, 理論方差爲:
Var[X]=p(1-p)

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=(0.8*(1-0.8)))
sel.fit_transform(X)

單變量特徵選擇 (Univariate feature selection)

單變量特徵選擇是對每個變量單獨做統計分析, 之後再根據統計指標來判斷變量是否重要.

問題類型 統計指標
分類問題 卡方檢驗, f_classif, 互信息( mutual_info_classif)
迴歸問題 皮爾遜相關係數(f_regression), 互信息迴歸(mutual_info_regression)

其他形式:

  • SelectKBest: 僅保留得分K名以內的所有特徵(TOP k)
  • SelectPercentile 僅保留指定前k百分比的數據(TOP k%)
  • 單變量檢驗, 例如假陽性比例SelectFpr, 僞發現率 SelectFdr, 族系誤差率SelectFwe.
  • GenericUnivariateSelect 允許設置特徵選擇參數, 不同的選擇策略可以使用超參數調優, 從而找到最佳單變量特徵選擇策略.

總的來說, 基於F檢驗的算法是用F檢驗估計來計算不同變量之間的線性依賴度(degree of linear dependency), 基於互信息的算法可以捕獲到任意一種統計依賴關係, 但是作爲一種非參數檢驗方法, 需要大量的樣本才能得到比較準確的結果.

如果數據的稀疏性很強, 可以選擇chi2, mutual_info_regression, mutual_info_classif 這些特徵選擇方法.

F檢驗與互信息

sklearn的官方教程給出了關於F檢驗和互信息區別的說明. 假設有3個特徵 x1, x2, x3 都服從[0,1]正態分佈,
目標函數如下:
y=x_1+sin(6pix_2)+0.1*N(0,1)
顯然, y的取值與x_3完全不相關. 下面這段代碼用了F檢驗和互信息兩種方法給出了x與y之間的依賴關係.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.feature_selection import f_regression, mutual_info_regression

np.random.seed(0)
X = np.random.rand(1000, 3)
y = X[:, 0] + np.sin(6*np.pi*X[:,1]) + 0.1*np.random.randn(1000)

f_test, _ = f_regression(X, y)
f_test /= np.max(f_test)

mi = mutual_info_regression(X, y)
mi = mi/np.max(mi)

plt.figure(figsize=(15,15))
for ii in range(3):
	plt.subplot(1, 3, ii+1)
	plt.scatter(X[:,ii], y, edgecolor=’black’, s=20)
	plt.xlabel(“$x_{}$”.format(ii+1), fontsize=14)
	if ii in range(3):
		plt.ylabel(“$y$”, fontsize=14)
	plt.title(“F-test={:.2f}, mi={:.2f}.format(f_test[i], mi[i]), fontsize=16)
plt.show()

在這裏插入圖片描述

圖中依次繪製了x_1, x_2, x_3與y之間的依賴關係, 圖上標題是對應特徵的統計指數(F-score和互信息), 可以看到, F-test更適合與線性關係的特徵, 而互信息係數在非線性
F檢驗得到的是數據之間的線性關係, 因此, F-test將x_1標記爲最具有識別力的參數(discriminative), 互信息可以識別變量之間任意形式(非線性的)依賴關係, 因此互信息將x_2標記爲最具有識別力的參數(或者說重要特徵).

下面給出了一個F 檢驗(ANOVA 方差檢驗) 與SVM的例子, 在SVM之前, 先用anova對數據做了降維.

"""
=================================================
SVM-Anova: SVM with univariate feature selection
=================================================

This example shows how to perform univariate feature selection before running a
SVC (support vector classifier) to improve the classification scores.
"""
print(__doc__)

import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm, datasets, feature_selection
from sklearn.cross_validation import cross_val_score
from sklearn.pipeline import Pipeline

###############################################################################
# Import some data to play with
digits = datasets.load_digits()
y = digits.target
# Throw away data, to be in the curse of dimension settings
y = y[:200]
X = digits.data[:200]
n_samples = len(y)
X = X.reshape((n_samples, -1))
# add 200 non-informative features
X = np.hstack((X, 2 * np.random.random((n_samples, 200))))

###############################################################################
# Create a feature-selection transform and an instance of SVM that we
# combine together to have an full-blown estimator
#feature_selection.f_classif:計算所提供樣本的方差分析F-值anova:方差分析
#feature_selection.SelectPercentile(k):只留下k值最高的一組特徵,返回最終的估計器
transform = feature_selection.SelectPercentile(feature_selection.f_classif)
#anova:Analysis of Variance(方差分析)
clf = Pipeline([('anova', transform), ('svc', svm.SVC(C=1.0))])

###############################################################################
# Plot the cross-validation score as a function of percentile of features
score_means = list()
score_stds = list()
percentiles = (1, 3, 6, 10, 15, 20, 30, 40, 60, 80, 100)

for percentile in percentiles:
    #clf.set_params:設置此估計器的參數。
    #使用網格搜索(grid search)和交叉驗證(cross validation)來選擇參數.
    #對方差分析中的參數percentile進行調節,實現多重比較檢驗
    #用於確定控制變量的不同水平對觀測變量的影響程度如何
    clf.set_params(anova__percentile=percentile)
    # Compute cross-validation score using 1 CPU
    #http://scikit-learn.org/dev/modules/generated/sklearn.model_selection.
    #cross_val_score.html#sklearn.model_selection.cross_val_score
    #cross_val_score:最簡單的交叉驗證方法,cv選擇折數,默認是3折交叉驗證
    this_scores = cross_val_score(clf, X, y, n_jobs=1)
    score_means.append(this_scores.mean())
    score_stds.append(this_scores.std())
#plt.errorbar以折線形式畫出均值和方差
plt.errorbar(percentiles, score_means, np.array(score_stds))

plt.title(
    'Performance of the SVM-Anova varying the percentile of features selected')
plt.xlabel('Percentile')
plt.ylabel('Prediction rate')

plt.axis('tight')

其他特徵選擇方法

重複性特徵刪除:

from sklearn.feature_selection import RFE

print(__doc__)

from sklearn.svm import SVC
from sklearn.datasets import load_digits
from sklearn.feature_selection import RFE
import matplotlib.pyplot as plt

# Load the digits dataset
digits = load_digits()
X = digits.images.reshape((len(digits.images), -1))
y = digits.target

# Create the RFE object and rank each pixel
svc = SVC(kernel="linear", C=1)
rfe = RFE(estimator=svc, n_features_to_select=1, step=1)
rfe.fit(X, y)
ranking = rfe.ranking_.reshape(digits.images[0].shape)

# Plot pixel ranking
plt.matshow(ranking, cmap=plt.cm.Blues)
plt.colorbar()
plt.title("Ranking of pixels with RFE")
plt.show()

神經影像分析中常用的searchlight方法,本質上也是一種recursive feature selection方法.

用模型選擇:

from sklearn.feature_selection import SelectFromModel

>>> 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
>>> X.shape
(150, 4)
>>> 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
(150, 3)

併入pipeline

特徵選擇可以作爲數據處理pipeline中的一個環節, 在覈心模型之前進行數據降維和特徵提取.

clf = Pipeline([
  ('feature_selection', SelectFromModel(LinearSVC(penalty="l1"))),
  ('classification', RandomForestClassifier())
])
clf.fit(X, y)

參考:
特徵工程: https://blog.csdn.net/jasonding1354/article/details/47171115
https://blog.csdn.net/sqiu_11/article/details/58719935
scikit learn 文檔: https://scikit-learn.org/stable/modules/feature_selection.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章