特徵選擇及基於Sklearn的實現

2021-01-14 數據科學DataScience

sklearn.feature_selection模塊被廣泛應用於樣本數據集的特徵選擇和特徵降維,以減少特徵數量,增強對特徵和特徵值之間的理解,提高預測準確性或提高在高維數據集上的性能。本文將依據官方文檔對sklearn.feature_selection模塊進行介紹。

通常來說主要從兩方面考慮來選擇特徵:

特徵發散程度:如果一個特徵不發散,如方差接近0,即樣本在該特徵上沒有顯著差異,這個特徵對於樣本區分的作用就很小。特徵與目標的相關性:與目標相關性高的特徵應該被優先選擇。

根據特徵選擇的形式又可以將特徵選擇方法分為3種:

過濾法Filter:按照發散程度或者相關性對各個特徵進行評分,通過設定閾值選擇特徵。包裝法Wrapper:根據目標函數(通常是預測效果評分)每次選擇或排除若干特徵。嵌入法Embedded:先使用機器學習算法和模型進行訓練得到各個特徵的權值係數,根據係數從大到小選擇特徵。

VarianceThreshold是特徵選擇中的基礎方法,它將刪除方差未達到閾值的特徵。認為如果輸入樣本中有超過一定閾值(如90%)的某一特徵值,那就可以判定該特徵作用不大。默認情況下刪除所有零方差的特徵,即在所有樣本中具有相同特徵值的特徵。適用於特徵值為離散型變量的特徵,若特徵值為連續型變量需要進行離散化。

例:假設我們有一個布爾特徵值的數據集,我們要刪除樣本中1或0比例超過80%的特徵。布爾特徵是伯努利隨機變量,其方差為 Var[X] = p*(1-p) ,則閾值為0.8*(1-0.8)。示例代碼如下所示,因第一列p=5/6>0.8,VarianceThreshold會將第一列刪除。

1from sklearn.feature_selection import VarianceThreshold
2X = [[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1, 1]]
3print('Initial X:\n', X)
4sel = VarianceThreshold(threshold=(0.8*(1-0.8)))
5X_selected = sel.fit_transform(X)
6print('Selected X:\n', X_selected)

單變量特徵選擇是通過單變量統計檢驗來選擇最佳特徵,Sciket-learn將特徵選擇用包含transform函數的對象來實現。該方法比較簡單,易於運行和理解,通常對於理解數據有較好的效果,但對特徵優化、提高泛化能力來說效果不一定好。

SelectKBest保留用戶指定的K個特徵(取top K)SelectPercentile保留用戶指定的百分比的特徵(取top k%)對於每個特徵使用通用的單變量統計檢驗:False positive率為SelectFpr,False discovery率為SelectFdr,Family wise error為SelectFwe。GenericUnivariateSelect使用可配置策略進行單變量特徵選擇,允許使用超參數搜索估計器選擇最佳的單變量選擇策略。

1
2from sklearn.datasets import load_iris
3from sklearn.feature_selection import SelectKBest
4from sklearn.feature_selection import chi2
5iris = load_iris()
6X, y = iris.data, iris.target
7print('Initial X shape: ', X.shape)
8X_selected = SelectKBest(chi2, k=2).fit_transform(X, y)
9print('Selected X shape: ', X_selected.shape)

通過將特徵輸入到評分函數,返回一個單變量的f_score(F檢驗的值)或p_value(P值,用於與顯著性水平做比較),SelectKBest和SelectPercentile只有評分,沒有P值。對於不同問題可用的方法如下:

分類問題:chi2, f_classif, mutual_info_classif回歸問題:f_regression, mutual_info_regression

   注意事項(一):不要在分類問題上使用回歸評分,得到的是無用的結果。如果使用稀疏數據(如用稀疏矩陣表示的數據)卡方檢驗(chi2)、互信息回歸(mutual_info_regression)、互信息分類(mutual_info_classif)在處理數據時可保持其稀疏性。 

1
2import numpy as np 
3import matplotlib.pyplot as plt
4%matplotlib inline
5from sklearn import datasets, svm
6from sklearn.feature_selection import SelectPercentile, f_classif
7
8iris = datasets.load_iris()
9E = np.random.uniform(0, 0.1, size=(len(iris.data), 20))
10X = np.hstack((iris.data, E))
11y = iris.target
12
13plt.figure(1)
14plt.clf()
15X_indices = np.arange(X.shape[-1])
16
17selector = SelectPercentile(f_classif, percentile=10)
18selector.fit(X, y)
19scores = -np.log10(selector.pvalues_)
20scores /= scores.max()
21plt.bar(X_indices - .45, scores, width=.2,label=r'Univariate score ($-Log(p_{value})$)', 
22        color='darkorange', edgecolor='black')
23
24clf = svm.SVC(kernel='linear')
25clf.fit(X,y)
26svm_weights = (clf.coef_ ** 2).sum(axis=0)
27svm_weights /= svm_weights.max()
28plt.bar(X_indices - .25, svm_weights, width=.2, label='SVM weight', color='navy', edgecolor='black')
29
30clf_selected = svm.SVC(kernel='linear')
31clf_selected.fit(selector.transform(X), y)
32svm_weights_selected = (clf_selected.coef_ ** 2).sum(axis=0)
33svm_weights_selected /= svm_weights_selected.max()
34plt.bar(X_indices[selector.get_support()] - .05, svm_weights_selected, width=.2, 
35        label='SVM weights after selection', color='c', edgecolor='black')
36
37plt.title("Comparing feature selection")
38plt.xlabel('Feature number')
39plt.yticks(())
40plt.axis('tight')
41plt.legend(loc='upper right')
42plt.show()

     注意事項(二):F檢驗用於評估兩個隨機變量的線性相關性,互信息方法可以計算任何類型的統計依賴關係,但作為非參數方法,需要更多的樣本來估計準確。

1
2
3from sklearn.feature_selection import f_regression, mutual_info_regression
4
5np.random.seed(0)
6X = np.random.rand(1000, 3)
7y = X[:, 0] + np.sin(6 * np.pi * X[:, 1]) + 0.1 * np.random.randn(1000)
8
9f_test, _ = f_regression(X, y)
10f_test /= np.max(f_test)
11mi = mutual_info_regression(X, y)
12mi /= np.max(mi)
13
14plt.figure(figsize=(15, 5))
15for i in range(3):
16    plt.subplot(1, 3, i + 1)
17    plt.scatter(X[:, i], y, edgecolor='black', s=20)
18    plt.xlabel("$x_{}$".format(i + 1), fontsize=14)
19    if i == 0:
20        plt.ylabel("$y$", fontsize=14)
21    plt.title("F-test={:.2f}, MI={:.2f}".format(f_test[i], mi[i]),
22              fontsize=16)
23plt.show()

對特徵含有權重的預測模型(如線性模型的權重係數),遞歸特徵消除(RFE)通過遞歸考慮越來越少的特徵集來選擇特徵。具體流程如下:首先,對估計器進行初始特徵集訓練,並通過coef_或feature_importances_屬性獲取特徵的重要性;然後,從當前的特徵中刪除最不重要的特徵;最後,對以上過程進行遞歸重複,直至達到所需的特徵數量。

1
2from sklearn.svm import SVC
3from sklearn.datasets import load_digits
4from sklearn.feature_selection import RFE
5
6digits = load_digits()
7X = digits.images.reshape((len(digits.images), -1))
8y = digits.target
9
10svc = SVC(kernel="linear", C=1)
11rfe = RFE(estimator=svc, n_features_to_select=1, step=1)
12rfe.fit(X, y)
13ranking = rfe.ranking_.reshape(digits.images[0].shape)
14
15plt.matshow(ranking, cmap=plt.cm.Blues)
16plt.colorbar()
17plt.title("Ranking of pixels with RFE")
18plt.show()

1
2from sklearn.model_selection import StratifiedKFold
3from sklearn.feature_selection import RFECV
4from sklearn.datasets import make_classification
5
6X, y = make_classification(n_samples=1000, n_features=25, n_informative=3,n_redundant=2, n_repeated=0, 
7                           n_classes=8, n_clusters_per_class=1, random_state=0)
8
9svc = SVC(kernel="linear")
10rfecv = RFECV(estimator=svc, step=1, cv=StratifiedKFold(2), scoring='accuracy')
11rfecv.fit(X, y)
12print("Optimal number of features : %d" % rfecv.n_features_)
13
14plt.figure()
15plt.xlabel("Number of features selected")
16plt.ylabel("Cross validation score (nb of correct classifications)")
17plt.plot(range(1, len(rfecv.grid_scores_) + 1), rfecv.grid_scores_)
18plt.show()

SelectFromModel與任何訓練後有coef_或feature_importances_屬性的預測模型一起使用,也被稱為meta-transformer。既可以指定閾值threshold將低於閾值的特徵刪除,也可以使用字符串參數調用內置的啟發式算法來設置閾值,包括平均值"mean"、中位數"median"及浮點數乘積"0.1*mean"。

1
2from sklearn.datasets import load_boston
3from sklearn.feature_selection import SelectFromModel
4from sklearn.linear_model import LassoCV
5
6boston = load_boston()
7X, y = boston['data'], boston['target']
8
9clf = LassoCV(cv=5)
10sfm = SelectFromModel(clf, threshold=0.25)
11sfm.fit(X, y)
12n_features = sfm.transform(X).shape[1]
13
14while n_features > 2:
15    sfm.threshold += 0.1
16    X_transform = sfm.transform(X)
17    n_features = X_transform.shape[1]
18
19plt.title("Features selected from Boston using SelectFromModel with threshold %0.3f." % sfm.threshold)
20feature1 = X_transform[:, 0]
21feature2 = X_transform[:, 1]
22plt.plot(feature1, feature2, 'r.')
23plt.xlabel("Feature 1")
24plt.ylabel("Feature 2")
25plt.ylim([np.min(feature2), np.max(feature2)])
26plt.show()

基於L1的特徵選擇

使用L1範數作為懲罰項的線性模型會得到稀疏解,即大部分特徵對應的稀疏為0。當需要減少特徵的維度以用於其它分類器時,可以通過SelectFromModel來選擇不為0的係數。常用於此目的的稀疏預測模型有linear_model.Lasso(回歸),linear_model.LogisticRegression 和 svm.LinearSVC(分類)。

1from sklearn.svm import LinearSVC
2from sklearn.datasets import load_iris
3from sklearn.feature_selection import SelectFromModel
4iris = load_iris()
5X, y = iris.data, iris.target
6print('X shape:', X.shape)
7
8lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X, y)
9model = SelectFromModel(lsvc, prefit=True)
10X_new = model.transform(X)
11print('X_new shape:', X_new.shape)

基於樹的特徵選擇

基於樹的預測模型(sklearn.tree模塊,sklearn.ensemble模塊)能夠用來計算特徵的重要程度,能夠用來去除不相關的特徵。

1from sklearn.ensemble import ExtraTreesClassifier
2from sklearn.datasets import load_iris
3from sklearn.feature_selection import SelectFromModel
4iris = load_iris()
5X, y = iris.data, iris.target
6print('X shape:', X.shape)
7clf = ExtraTreesClassifier(n_estimators=10)
8clf = clf.fit(X, y)
9print('feature_importance:', clf.feature_importances_)  
10model = SelectFromModel(clf, prefit=True)
11X_new = model.transform(X)
12print('X_new shape:', X_new.shape)

1
2import numpy as np
3import matplotlib.pyplot as plt
4from sklearn.datasets import make_classification
5from sklearn.ensemble import ExtraTreesClassifier
6
7
8X, y = make_classification(n_samples=1000, n_features=10, n_informative=3, n_redundant=0,
9                           n_repeated=0, n_classes=2, random_state=0, shuffle=False)
10
11forest = ExtraTreesClassifier(n_estimators=250, random_state=0)
12forest.fit(X, y)
13importances = forest.feature_importances_
14std = np.std([tree.feature_importances_ for tree in forest.estimators_], axis=0)
15indices = np.argsort(importances)[::-1]
16
17print("Feature ranking:")
18for f in range(X.shape[1]):
19    print("%d. feature %d (%f)" % (f + 1, indices[f], importances[indices[f]]))
20
21plt.figure()
22plt.title("Feature importances")
23plt.bar(range(X.shape[1]), importances[indices], color="r", yerr=std[indices], align="center")
24plt.xticks(range(X.shape[1]), indices)
25plt.xlim([-1, X.shape[1]])
26plt.show()

1
2import matplotlib.pyplot as plt
3from sklearn.datasets import fetch_olivetti_faces
4from sklearn.ensemble import ExtraTreesClassifier
5
6
7data = fetch_olivetti_faces()
8X = data.images.reshape((len(data.images), -1))
9y = data.target
10mask = y < 5  
11X = X[mask]
12y = y[mask]
13
14
15forest = ExtraTreesClassifier(n_estimators=1000, max_features=128, n_jobs=1, random_state=0)
16forest.fit(X, y)
17importances = forest.feature_importances_
18importances = importances.reshape(data.images[0].shape)
19
20plt.matshow(importances, cmap=plt.cm.hot)
21plt.title("Pixel importances with forests of trees")
22plt.show()

特徵選擇常常被當作機器學習前的預處理步驟之一。在scikit-learn中可以使用sklearn.pipeline.Pipeline,以下示例代碼將LinearSVC 和SelectFromModel結合來評估特徵的重要性進行特徵選擇,之後用RandomForestClassifier模型使用轉換後的輸出(即被選出的相關特徵)進行訓練。

1from sklearn.pipeline import Pipeline
2from sklearn.datasets import load_iris
3from sklearn.svm import LinearSVC
4from sklearn.ensemble import RandomForestClassifier
5iris = load_iris()
6X, y = iris.data, iris.target
7clf = Pipeline([
8    ('feature_selection', SelectFromModel(LinearSVC(penalty="l1", dual=False, max_iter=3000))),
9    ('classfication', RandomForestClassifier(n_estimators=100))
10])
11clf.fit(X, y)

相關焦點

  • 專欄 | 基於 Jupyter 的特徵工程手冊:特徵選擇(四)
    作者:陳穎祥、楊子晗
  • 運用sklearn進行線性判別分析(LDA)代碼實現
    基於sklearn的線性判別分析(LDA)代碼實現一、前言及回顧本文記錄使用sklearn庫實現有監督的數據降維技術——線性判別分析(LDA)。在上一篇LDA線性判別分析原理及python應用(葡萄酒案例分析),我們通過詳細的步驟理解LDA內部邏輯實現原理,能夠更好地掌握線性判別分析的內部機制。
  • 機器學習之基於sklearn的KMeans聚類
    聚類算法,無監督學習的代表算法,又叫做「無監督分類」即在訓練的時候只需要特徵矩陣,不需要真實值標籤可以有效地幫助我們探索數據的自然分布一、KMeans算法的運行過程運行的流程如下:自動聚類時的質心點的每步驟變化如下:
  • 使用scikit-learn進行特徵選擇
    scikit-learn中提供了用於特徵選擇的模塊feature_selection,主要方法包括方差移除法,卡方檢驗法,基於L1的特徵選擇和基於樹的特徵選擇
  • SKlearn實現鳶尾花分類:決策樹
    其中,節點表示特徵、屬性或者一個類。而有向邊包含有判斷條件。如圖所示,決策樹從根節點開始延伸,經過不同的判斷條件後,到達不同的子節點。而上層子節點又可以作為父節點被進一步劃分為下層子節點。一般情況下,我們從根節點輸入數據,經過多次判斷後,這些數據就會被分為不同的類別。這就構成了一顆簡單的分類決策樹。特徵選擇特徵選擇是建立決策樹之前十分重要的一步。
  • 使用python+sklearn實現概率PCA和因子分析進行模型選擇
    概率PCA和因子分析都是概率模型,新數據的似然性(likelihood)可用於模型選擇和協方差估計
  • 機器學習:特徵選擇和降維實例
    根據維基百科,「特徵選擇是選擇用於模型構建的相關特徵的子集的過程」,或者換句話說,選擇最重要的特徵。在正常情況下,領域知識起著重要作用,我們可以選擇我們認為最重要的特徵。例如,在預測房價時,臥室和面積通常被認為是重要的。
  • 特徵選擇怎麼做?這篇文章告訴你
    如果添加的特徵比必要的特徵多,那麼我們的模型性能將下降(因為添加了噪聲)。真正的挑戰是找出哪些特徵是最佳的使用特徵(這實際上取決於我們提供的數據量和我們正在努力實現的任務的複雜性)。這就是特徵選擇技術能夠幫到我們的地方!
  • 5個特徵選擇算法,讓你的數據處理得心應手
    本文將會介紹一些處理數據時最常用的特徵選擇技術。我們經常遇到這樣的情況:在創建了大量特徵後,又需要減少數量,最後再使用相關性或者基於樹的方法來找出其中的重要特徵。那麼,如何讓這些方法變得更有結構呢?為何要進行特徵選擇?
  • 機器學習之sklearn基礎教程!
    本文在基於讀者已經基本了解這些基本算法的原理以及推導的基礎上,使用sklearn工具包進行算法實踐,如果大家沒有掌握基本算法原理,文中也會給出一些優秀的連結方便大家學習。如果大家對基本分類算法的基本原理有需求,可以在評論區寫下自己的需求,我們會根據大家的意見推出相應的分享。
  • 機器學習之決策樹在sklearn中的實現
    1 導入需要的算法庫和模塊<pre spellcheck="false" contenteditable="true" cid="n11" mdtype="fences" >from sklearn import tree #導入tree模塊from sklearn.datasets import load_wine #導入紅酒數據集from sklearn.model_selection
  • 機器學習中特徵選擇怎麼做?這篇文章告訴你
    真正的挑戰是找出哪些特徵是最佳的使用特徵(這實際上取決於我們提供的數據量和我們正在努力實現的任務的複雜性)。這就是特徵選擇技術能夠幫到我們的地方!圖 1:分類器性能和維度之間的關係▍特徵選擇有許多不同的方法可用於特徵選擇。其中最重要的是:1.過濾方法=過濾我們的數據集,只取包含所有相關特徵的子集(例如,使用 Pearson 相關的相關矩陣)。
  • 如何用sklearn創建機器學習分類器?這裡有一份上手指南
    讀完這篇文章,你將學到:導入和轉換.csv文件,開啟sklearn之旅檢查數據集並選擇相關特徵用sklearn訓練不同的數據分類器分析結果,進一步改造模型第一步:導入數據找到合適的數據下載完成後,我們不難猜到,要做的第一件事肯定是加載並且檢查數據的結構。這裡我推薦大家使用Pandas。
  • 支持向量機+sklearn繪製超平面
    特徵空間的維數可能非常高。4.SVM 應用實例 由於 SVM 算法本身的實現較為複雜,所以這裡就不給出如何實現SVM的代碼,採用 sklearn庫來幫助我們學習SVM 的應用例子。中對超平面的表示並不是 y = kx +b 這樣的,而是把 x作為第一個特徵 x0, y作為另一個特徵x1,表示為:
  • 如何用Python計算機器學習中特徵的重要程度?
    基於CART的特徵重要性4.2. 基於隨機森林的特徵重要性4.3. 基於XGBoost的特徵重要性5.隨機排序特徵重要性5.1. 隨機排序(回歸)中的特徵重要性5.2.特徵重要性可用於改進預測模型可以使用的重要性得分來選擇要刪除的特徵(最低得分)或要保留的特徵(最高得分)。這是一種特徵選擇,可以簡化正在建模的問題,加快建模過程(刪除特徵稱為降維),在某些情況下,還可以改善模型的性能。
  • 基於 Python 實現動態分類器集成學習
    動態分類器選擇是一種用於分類預測建模的集成學習算法。該技術涉及在訓練數據集上擬合多個機器學習模型,然後基於要預測的示例的特定細節,選擇在進行預測時預期表現最佳的模型。這可以通過以下方法實現:使用k最近鄰模型在訓練數據集中找到最接近要預測的新示例的示例,評估該鄰域中池中的所有模型,並使用在鄰域中表現最佳的模型來對新示例做出預測。
  • Python機器學習sklearn模塊——決策樹
    決策樹可以用來解決分類與回歸問題,是一種非線性模型;一課決策樹一般包含一個根節點、若干個內部節點和若干個葉節點;生產決策樹最關鍵的是如何選擇最優劃分屬性,我們希望分支節點所包含的樣本近可能的屬於同一類別,即節點的「純度」越來越高;而評估樣本集合純度的常用指標有信息增益、增益率和基尼指數;決策樹容易出現過擬合狀況,因為它們可以通過精確的描述每個訓練樣本的 特徵而構建出複雜的決策樹
  • 機器學習之sklearn中的降維算法
    PCA與SVDsklearn中降維算法都被包括在模塊decomposition中,這個模塊本質是一個矩陣分解模塊。在過去的十年中,如果要討論算法進步的先鋒,矩陣分解可以說是獨樹一幟。矩陣分解可以用在降維,深度學習,聚類分析,數據預處理,低緯度特徵學習,推薦系統,大數據分析等領域。
  • 理解隨機森林:基於Python的實現和解釋
    在訓練過程中,我們會向模型提供特徵和標籤,使其能夠學習基於這些特徵對數據點進行分類。我們沒有針對這個簡單問題的測試集,但在進行測試時,我們只向模型提供特徵,然後讓其給出對標籤的預測。比如,在頂部(根)節點中,有 44.4% 的可能性將一個隨機選擇的數據點基於該節點的樣本標籤分布不正確地分類。基尼不純度是決策樹決定用於分割節點(有關數據的問題)的特徵值的方式。樹會通過所有用於分割的特徵來進行搜索,以最大化地降低不純度。
  • 數值數據的特徵預處理
    這就是特徵預處理的由來,特徵預處理將原始數據轉換為機器學習模型可用的數據。不同類型的機器學習模型首先,讓我們看看機器學習模型的不同類別。這裡,我們將模型分為兩種類型:基於樹的模型:基於樹的模型是一種監督學習模型,能夠在捕捉複雜非線性關係的同時提供高精度和穩定性。基於樹的決策樹模型有隨機森林模型和梯度增強決策樹模型。