1.特征選擇
特征選擇是降維的一種方法,即選擇對預測結果相關度高的特征或者消除相似度高的特征,以提高估計函數的准確率或者提高多維度數據集上的性能。
2.刪除低方差特征
1)思路:設置一個閥值,對每個特征求方差,如果所求方差低於這個閥值,則刪除此特征。默認情況下會刪除0方差。
2)核心函數
sklearn.feature_selection.VarianceThreshold
3)主要參數:
threshold :設置的閥值
補充說明:
官網給出的是一個布爾值的數據集,閥值的表示方式為下面的公式:
示例寫法:sel = VarianceThreshold(threshold=(0.8 * (1 - 0.8)))
經過測試,非布爾值的數據集也適用,並且直接寫成:threshold=0.16 也是可以的。
對於二維矩陣,求的是每列的方差,然后和閥值比較。
4)示例
為了更好的說明用刪除低方差的方式進行特征選擇后,新的數據集不會影響預測結果或者不會造成太大的影響,這里選擇一個官方提供的數據集進行對比。這個數據集是關於花朵類型判斷的:包含150個樣本數據,每個樣本數據包含4個特征,這些樣本數據屬於3類,每類50個樣本。
使用決策樹進行分類預測。
詳細代碼如下:

from sklearn.datasets import load_iris from sklearn import tree from sklearn.feature_selection import VarianceThreshold import numpy as np ##加載數據 iris = load_iris() ##設置篩選閥值 sel = VarianceThreshold(threshold=(.7 * (1 - .7))) ##設置訓練集和標簽集 X, y = iris.data, iris.target print("原始數據:") print(X.shape) #(150, 4) #篩選數據 X_new = sel.fit_transform(X) print("新數據集:") print(X_new.shape) #(150, 3) ##設置分類函數:決策樹 clf = tree.DecisionTreeClassifier() ##訓練數據 clf.fit(X, y) ##預測數據 y_pred = clf.predict(X) ##使用選擇特征后的數據進行訓練 clf.fit(X_new, y) ##在新數據集上進行預測 y_pred1 = clf.predict(X_new) ##原始數據的預測結果和真實結果的對比 cnt = 0 for i in range(len(y)): if y_pred[i] == y[i]: cnt += 1 print("原始數據的預測結果和真實結果相同的個數:") print(cnt) ##新數據集和真實結果的對比 cnt = 0 for i in range(len(y)): if y_pred1[i]== y[i]: cnt += 1 print("新數據集的預測結果和真實結果相同的個數:") print(cnt) ##原始數據的預測結果和新數據的預測結果的對比 cnt = 0 for i in range(len(y)): if y_pred[i] == y_pred1[i]: cnt += 1 print("原始據集的預測結果和新數據集預測結果相同的個數:") print(cnt)
輸出結果:
原始數據: (150, 4) 新數據集: (150, 3) 原始數據的預測結果和真實結果相同的個數: 150 新數據集的預測結果和真實結果相同的個數: 150 原始據集的預測結果和新數據集預測結果相同的個數: 150
從結果可以看出,數據從150×4的矩陣變成了150×3的矩陣,但是完全沒有對預測結果造成任何影響。
3.單變量特征選擇
(下面的翻譯可能不是很准確)
1)思路:對每個特征做基於統計的檢驗,從而選擇出最佳特征。
2)可用的函數
SelectPercentile:根據最高分數的百分位數選擇特征。
SelectKBest:根據k最高分選擇特征。
SelectFpr:基於假陽性率測試選擇特征。
SelectFdr:根據估計的虛假發現率選擇特征。
SelectFwe:根據家庭錯誤率選擇功能(這個翻譯感覺很怪:based on family-wise error rate)
GenericUnivariateSelect:具有可配置模式的單變量特征選擇器。
3)可用的統計方法(上面函數的參數):
f_classif:用於分類任務的標簽/特征之間方差分析的F值。
mutual_info_classif:離散目標的相互信息。
chi2:用於分類任務的非負性特征的卡方統計。
f_regression:用於回歸任務的標簽/特征之間的F值。
mutual_info_regression:連續目標的相互信息。
4)示例
依然使用上面的關於花朵的數據集和決策樹分類方法。
詳細代碼如下:

from sklearn.datasets import load_iris from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 from sklearn import tree import numpy as np ##加載數據 iris = load_iris() ##設置訓練集和標簽集 X, y = iris.data, iris.target print("原始數據:") print(X.shape) #(150, 4) ##選擇關鍵特征 X_new = SelectKBest(chi2, k=2).fit_transform(X, y) print("新數據集:") print(X_new.shape) #(150, 2) ##設置分類函數:決策樹 clf = tree.DecisionTreeClassifier() ##訓練數據 clf.fit(X, y) ##預測數據 y_pred = clf.predict(X) ##使用選擇特征后的數據進行訓練 clf.fit(X_new, y) ##在新數據集上進行預測 y_pred1 = clf.predict(X_new) ##原始數據的預測結果和真實結果的對比 cnt = 0 for i in range(len(y)): if y_pred[i] == y[i]: cnt += 1 print("原始數據的預測結果和真實結果相同的個數:") print(cnt) ##新數據集和真實結果的對比 cnt = 0 for i in range(len(y)): if y_pred1[i]== y[i]: cnt += 1 print("新數據集的預測結果和真實結果相同的個數:") print(cnt) ##原始數據的預測結果和新數據的預測結果的對比 cnt = 0 for i in range(len(y)): if y_pred[i] == y_pred1[i]: cnt += 1 print("原始據集的預測結果和新數據集預測結果相同的個數:") print(cnt)
輸出結果:
原始數據: (150, 4) 新數據集: (150, 2) 原始數據的預測結果和真實結果相同的個數: 150 新數據集的預測結果和真實結果相同的個數: 149 原始據集的預測結果和新數據集預測結果相同的個數: 149
從結果可以看出,原始的數據集從150×4變成了150×2,但是預測的結果只有一個誤差。
4.使用SelectFromModel進行特征選擇
1)思路:SelectFromModel是一種元變壓器,可用於任何在擬合后有coef_或feature_importances_屬性的擬合函數。如果相應的coef_或feature_importances_值低於提供的threshold參數(閥值),則認為這些特征是是不重要的並且刪除。除了數值上指定閾值外,還有內置的啟發式算法,用於使用字符串參數來查找閾值。可用的啟發式算法是“平均值”,“中位數”和浮點倍數,如“0.1 *mean”。
2)由上面SelectFromModel的思路可知,首先需要進行一次擬合,然后才通過SelectFromModel選擇特征。根據第一次擬合函數的不同,分為兩類:
a)基於L1的特征選擇
詳細代碼:

from sklearn.datasets import load_iris from sklearn.svm import LinearSVC from sklearn.feature_selection import SelectFromModel from sklearn import tree import numpy as np ##加載數據 iris = load_iris() ##設置訓練集和標簽集 X, y = iris.data, iris.target print("原始數據:") print(X.shape) #(150, 4) ##選擇關鍵特征 lsvc = LinearSVC(C=0.01, penalty="l1", dual=False) lsvc = lsvc.fit(X, y) model = SelectFromModel(lsvc, prefit=True) X_new = model.transform(X) print("新數據集:") print(X_new.shape) #(150, 3) ##設置分類函數:決策樹 clf = tree.DecisionTreeClassifier() ##訓練數據 clf.fit(X, y) ##預測數據 y_pred = clf.predict(X) ##使用選擇特征后的數據進行訓練 clf.fit(X_new, y) ##在新數據集上進行預測 y_pred1 = clf.predict(X_new) ##原始數據的預測結果和真實結果的對比 cnt = 0 for i in range(len(y)): if y_pred[i] == y[i]: cnt += 1 print("原始數據的預測結果和真實結果相同的個數:") print(cnt) ##新數據集和真實結果的對比 cnt = 0 for i in range(len(y)): if y_pred1[i]== y[i]: cnt += 1 print("新數據集的預測結果和真實結果相同的個數:") print(cnt) ##原始數據的預測結果和新數據的預測結果的對比 cnt = 0 for i in range(len(y)): if y_pred[i] == y_pred1[i]: cnt += 1 print("原始據集的預測結果和新數據集預測結果相同的個數:") print(cnt)
輸出結果:
原始數據: (150, 4) 新數據集: (150, 3) 原始數據的預測結果和真實結果相同的個數: 150 新數據集的預測結果和真實結果相同的個數: 150 原始據集的預測結果和新數據集預測結果相同的個數: 150
從結果可以看出,數據從150×4變成了150×3,但是預測結果沒有受影響。
b)基於樹的特征選擇
詳細代碼:

from sklearn.datasets import load_iris from sklearn.ensemble import ExtraTreesClassifier from sklearn.feature_selection import SelectFromModel from sklearn import tree import numpy as np ##加載數據 iris = load_iris() ##設置訓練集和標簽集 X, y = iris.data, iris.target print("原始數據:") print(X.shape) #(150, 4) ##選擇關鍵特征 etc = ExtraTreesClassifier() etc = etc.fit(X,y) model = SelectFromModel(etc, prefit=True) X_new = model.transform(X) print("新數據集:") print(X_new.shape) #(150, 2) ##設置分類函數:決策樹 clf = tree.DecisionTreeClassifier() ##訓練數據 clf.fit(X, y) ##預測數據 y_pred = clf.predict(X) ##使用選擇特征后的數據進行訓練 clf.fit(X_new, y) ##在新數據集上進行預測 y_pred1 = clf.predict(X_new) ##原始數據的預測結果和真實結果的對比 cnt = 0 for i in range(len(y)): if y_pred[i] == y[i]: cnt += 1 print("原始數據的預測結果和真實結果相同的個數:") print(cnt) ##新數據集和真實結果的對比 cnt = 0 for i in range(len(y)): if y_pred1[i]== y[i]: cnt += 1 print("新數據集的預測結果和真實結果相同的個數:") print(cnt) ##原始數據的預測結果和新數據的預測結果的對比 cnt = 0 for i in range(len(y)): if y_pred[i] == y_pred1[i]: cnt += 1 print("原始據集的預測結果和新數據集預測結果相同的個數:") print(cnt)
輸出結果:
原始數據: (150, 4) 新數據集: (150, 2) 原始數據的預測結果和真實結果相同的個數: 150 新數據集的預測結果和真實結果相同的個數: 149 原始據集的預測結果和新數據集預測結果相同的個數: 149
從結果看出,數據集從150×4變成了150×2,出現了一個誤差。
3)上述代碼的選擇特征,然后預測,也可簡寫成如下形式:
clf = Pipeline([ ('feature_selection', SelectFromModel(LinearSVC(C=0.01, penalty="l1", dual=False))), ('classification', tree.DecisionTreeClassifier()) ]) clf.fit(X, y)