機器學習中特徵選擇怎麼做?這篇文章告訴你

視學演算法發表於2020-04-06

來源 | AI開發者

簡  介

據《福布斯》報導,每天大約會有 250 萬位元組的資料被產生。然後,可以使用資料科學和機器學習技術對這些資料進行分析,以便提供分析和作出預測。儘管在大多數情況下,在開始任何統計分析之前,需要先對最初收集的資料進行預處理。有許多不同的原因導致需要進行預處理分析,例如:

  • 收集的資料格式不對(如 SQL 資料庫、JSON、CSV 等)

  • 缺失值和異常值

  • 標準化

  • 減少資料集中存在的固有噪聲(部分儲存資料可能已損壞)

  • 資料集中的某些功能可能無法收集任何資訊以供分析

在本文中,我將介紹如何使用 python 減少 kaggle Mushroom Classification 資料集中的特性數量。本文中使用的所有程式碼在 kaggle 和我的 github 帳號上都有。

減少統計分析期間要使用的特徵的數量可能會帶來一些好處,例如:

  • 提高精度

  • 降低過擬合風險

  • 加快訓練速度

  • 改進資料視覺化

  • 增加我們模型的可解釋性

事實上,統計上證明,當執行機器學習任務時,存在針對每個特定任務應該使用的最佳數量的特徵(圖 1)。如果新增的特徵比必要的特徵多,那麼我們的模型效能將下降(因為新增了噪聲)。真正的挑戰是找出哪些特徵是最佳的使用特徵(這實際上取決於我們提供的資料量和我們正在努力實現的任務的複雜性)。這就是特徵選擇技術能夠幫到我們的地方!

機器學習中特徵選擇怎麼做?這篇文章告訴你

圖 1:分類器效能和維度之間的關係

特徵選擇

有許多不同的方法可用於特徵選擇。其中最重要的是:

1.過濾方法=過濾我們的資料集,只取包含所有相關特徵的子集(例如,使用 Pearson 相關的相關矩陣)。

2.遵循過濾方法的相同目標,但使用機器學習模型作為其評估標準(例如,向前/向後/雙向/遞迴特徵消除)。我們將一些特徵輸入機器學習模型,評估它們的效能,然後決定是否新增或刪除特徵以提高精度。因此,這種方法可以比濾波更精確,但計算成本更高。

3.嵌入方法。與過濾方法一樣,嵌入方法也使用機器學習模型。這兩種方法的區別在於,嵌入的方法檢查 ML 模型的不同訓練迭代,然後根據每個特徵對 ML 模型訓練的貢獻程度對每個特徵的重要性進行排序。

機器學習中特徵選擇怎麼做?這篇文章告訴你

圖 2:過濾器、包裝器和嵌入式方法表示 [3]

實踐

在本文中,我將使用 Mushroom Classification 資料集,通過檢視給定的特徵來嘗試預測蘑菇是否有毒。在這樣做的同時,我們將嘗試不同的特徵消除技術,看看它們會如何影響訓練時間和模型整體的精度。

首先,我們需要匯入所有必需的庫。

機器學習中特徵選擇怎麼做?這篇文章告訴你

我們將在本例中使用的資料集如下圖所示。

機器學習中特徵選擇怎麼做?這篇文章告訴你

圖 3:Mushroom Classification 資料集

在將這些資料輸入機器學習模型之前,我決定對所有分類變數進行 one hot 編碼,將資料分為特徵(x)和標籤(y),最後在訓練集和測試集中進行。

X = df.drop(['class'], axis = 1)
Y = df['class']
X = pd.get_dummies(X, prefix_sep='_')
Y = LabelEncoder().fit_transform(Y)

X2 = StandardScaler().fit_transform(X)

X_Train, X_Test, Y_Train, Y_Test = train_test_split(X2, Y, test_size = 0.30,  random_state = 101)

特徵重要性

基於集合的決策樹模型(如隨機森林)可以用來對不同特徵的重要性進行排序。瞭解我們的模型最重要的特徵對於理解我們的模型如何做出預測(使其更易於解釋)是至關重要的。同時,我們可以去掉那些對我們的模型沒有任何好處的特徵。

start = time.process_time()
trainedforest = RandomForestClassifier(n_estimators=700).fit(X_Train,Y_Train)
print(time.process_time() - start)
predictionforest = trainedforest.predict(X_Test)
print(confusion_matrix(Y_Test,predictionforest))
print(classification_report(Y_Test,predictionforest))

如下圖所示,使用所有特徵訓練一個隨機森林分類器,在大約 2.2 秒的訓練時間內獲得 100% 的準確率。在下面的每個示例中,每個模型的訓練時間都將列印在每個片段的第一行,供你參考。

機器學習中特徵選擇怎麼做?這篇文章告訴你

一旦我們的隨機森林分類器得到訓練,我們就可以建立一個特徵重要性圖,看看哪些特徵對我們的模型預測來說是最重要的(圖 4)。在本例中,下面只顯示了前 7 個特性。

figure(num=None, figsize=(20, 22), dpi=80, facecolor='w', edgecolor='k')

feat_importances = pd.Series(trainedforest.feature_importances_, index= X.columns)
feat_importances.nlargest(7).plot(kind='barh')

機器學習中特徵選擇怎麼做?這篇文章告訴你

圖 4:特徵重要性圖

現在我們知道了哪些特徵被我們的隨機森林認為是最重要的,我們可以嘗試使用前 3 個來訓練我們的模型。

X_Reduced = X[['odor_n','odor_f', 'gill-size_n','gill-size_b']]
X_Reduced = StandardScaler().fit_transform(X_Reduced)
X_Train2, X_Test2, Y_Train2, Y_Test2 = train_test_split(X_Reduced, Y, test_size = 0.30,  random_state = 101)

start = time.process_time()
trainedforest = RandomForestClassifier(n_estimators=700).fit(X_Train2,Y_Train2)
print(time.process_time() - start)
predictionforest = trainedforest.predict(X_Test2)
print(confusion_matrix(Y_Test2,predictionforest))
print(classification_report(Y_Test2,predictionforest))

正如我們在下面看到的,僅僅使用 3 個特徵,只會導致準確率下降 0.03%,訓練時間減少一半。

機器學習中特徵選擇怎麼做?這篇文章告訴你

我們還可以通過視覺化一個訓練過的決策樹來理解如何進行特徵選擇。

start = time.process_time()
trainedtree = tree.DecisionTreeClassifier().fit(X_Train, Y_Train)
print(time.process_time() - start)
predictionstree = trainedtree.predict(X_Test)
print(confusion_matrix(Y_Test,predictionstree))
print(classification_report(Y_Test,predictionstree))

機器學習中特徵選擇怎麼做?這篇文章告訴你

樹結構頂部的特徵是我們的模型為了執行分類而保留的最重要的特徵。因此,只選擇頂部的前幾個特徵,而放棄其他特徵,可能建立一個準確度非常可觀的模型。

import graphviz
from sklearn.tree import DecisionTreeClassifier, export_graphviz


data = export_graphviz(trainedtree,out_file=None,feature_names= X.columns,
        class_names=['edible', 'poisonous'], 
        filled=True, rounded=True, 
        max_depth=2,
        special_characters=True)
graph = graphviz.Source(data)
graph

機器學習中特徵選擇怎麼做?這篇文章告訴你

圖 5:決策樹視覺化

遞迴特徵消除(RFE)

遞迴特徵消除(RFE)將機器學習模型的例項和要使用的最終期望特徵數作為輸入。然後,它遞迴地減少要使用的特徵的數量,採用的方法是使用機器學習模型精度作為度量對它們進行排序。

建立一個 for 迴圈,其中輸入特徵的數量是我們的變數,這樣就可以通過跟蹤在每個迴圈迭代中註冊的精度,找出我們的模型所需的最佳特徵數量。使用 RFE 支援方法,我們可以找出被評估為最重要的特徵的名稱(rfe.support 返回一個布林列表,其中 true 表示一個特徵被視為重要,false 表示一個特徵不重要)。

from sklearn.feature_selection import RFE

model = RandomForestClassifier(n_estimators=700)
rfe = RFE(model, 4)
start = time.process_time()
RFE_X_Train = rfe.fit_transform(X_Train,Y_Train)
RFE_X_Test = rfe.transform(X_Test)
rfe = rfe.fit(RFE_X_Train,Y_Train)
print(time.process_time() - start)
print("Overall Accuracy using RFE: ", rfe.score(RFE_X_Test,Y_Test))

機器學習中特徵選擇怎麼做?這篇文章告訴你

SelecFromModel

selectfrommodel 是另一種 scikit 學習方法,可用於特徵選擇。此方法可用於具有 coef 或 feature 重要性屬性的所有不同型別的 scikit 學習模型(擬合後)。與 rfe 相比,selectfrommodel 是一個不太可靠的解決方案。實際上,selectfrommodel 只是根據計算出的閾值(不涉及優化迭代過程)刪除不太重要的特性。

為了測試 selectfrommodel 的有效性,我決定在這個例子中使用一個 ExtraTreesClassifier。

ExtratreesClassifier(極端隨機樹)是基於樹的整合分類器,與隨機森林方法相比,它可以產生更少的方差(因此減少了過擬合的風險)。隨機森林和極隨機樹的主要區別在於極隨機樹中節點的取樣不需要替換。

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

model = ExtraTreesClassifier()
start = time.process_time()
model = model.fit(X_Train,Y_Train)
model = SelectFromModel(model, prefit=True)
print(time.process_time() - start)
Selected_X = model.transform(X_Train)

start = time.process_time()
trainedforest = RandomForestClassifier(n_estimators=700).fit(Selected_X, Y_Train)
print(time.process_time() - start)
Selected_X_Test = model.transform(X_Test)
predictionforest = trainedforest.predict(Selected_X_Test)
print(confusion_matrix(Y_Test,predictionforest))
print(classification_report(Y_Test,predictionforest))

機器學習中特徵選擇怎麼做?這篇文章告訴你

相關矩陣分析

為了減少資料集中的特徵數量,另一種可能的方法是檢查特徵與標籤的相關性。

使用皮爾遜相關,我們的返回係數值將在-1 和 1 之間變化:

  • 如果兩個特徵之間的相關性為 0,則意味著更改這兩個特徵中的任何一個都不會影響另一個。

  • 如果兩個特徵之間的相關性大於 0,這意味著增加一個特徵中的值也會增加另一個特徵中的值(相關係數越接近 1,兩個不同特徵之間的這種聯絡就越強)。

  • 如果兩個特徵之間的相關性小於 0,這意味著增加一個特徵中的值將使減少另一個特徵中的值(相關性係數越接近-1,兩個不同特徵之間的這種關係將越強)。

在這種情況下,我們將只考慮與輸出變數至少 0.5 相關的特性。

Numeric_df = pd.DataFrame(X)
Numeric_df['Y'] = Y
corr= Numeric_df.corr()
corr_y = abs(corr["Y"])
highest_corr = corr_y[corr_y >0.5]
highest_corr.sort_values(ascending=True)

機器學習中特徵選擇怎麼做?這篇文章告訴你

我們現在可以通過建立一個相關矩陣來更仔細地研究不同相關特徵之間的關係。

figure(num=None, figsize=(12, 10), dpi=80, facecolor='w', edgecolor='k')

corr2 = Numeric_df[['bruises_f' , 'bruises_t' , 'gill-color_b' , 'gill-size_b' ,  'gill-size_n' , 'ring-type_p' , 'stalk-surface-below-ring_k' ,  'stalk-surface-above-ring_k' , 'odor_f', 'odor_n']].corr()

sns.heatmap(corr2, annot=True, fmt=".2g")

機器學習中特徵選擇怎麼做?這篇文章告訴你

圖 6:最高相關特徵的相關矩陣

在這項分析中,另一個可能要控制的方面是檢查所選變數是否彼此高度相關。如果是的話,我們就只需要保留其中一個相關的,去掉其他的。

最後,我們現在可以只選擇與 y 相關度最高的特徵,訓練/測試一個支援向量機模型來評估該方法的結果。

機器學習中特徵選擇怎麼做?這篇文章告訴你

機器學習中特徵選擇怎麼做?這篇文章告訴你

單變數選擇

單變數特徵選擇是一種統計方法,用於選擇與我們對應標籤關係最密切的特徵。使用 selectkbest 方法,我們可以決定使用哪些指標來評估我們的特徵,以及我們希望保留的 k 個最佳特徵的數量。根據我們的需要,提供不同型別的評分函式:

  • Classification = chi2, f_classif, mutual_info_classif

  • Regression = f_regression, mutual_info_regression

在本例中,我們將使用 chi2(圖 7)。

機器學習中特徵選擇怎麼做?這篇文章告訴你

圖 7:卡方公式 [4]

卡方(chi-squared,chi2)可以將非負值作為輸入,因此,首先,我們在 0 到 1 之間的範圍內縮放輸入資料。

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

min_max_scaler = preprocessing.MinMaxScaler()
Scaled_X = min_max_scaler.fit_transform(X2)

X_new = SelectKBest(chi2, k=2).fit_transform(Scaled_X, Y)
X_Train3, X_Test3, Y_Train3, Y_Test3 = train_test_split(X_new, Y, test_size = 0.30,  random_state = 101)
start = time.process_time()
trainedforest = RandomForestClassifier(n_estimators=700).fit(X_Train3,Y_Train3)
print(time.process_time() - start)
predictionforest = trainedforest.predict(X_Test3)
print(confusion_matrix(Y_Test3,predictionforest))
print(classification_report(Y_Test3,predictionforest))

機器學習中特徵選擇怎麼做?這篇文章告訴你

套索迴歸

當將正則化應用於機器學習模型時,我們在模型引數上加上一個懲罰,以避免我們的模型試圖太接近我們的輸入資料。通過這種方式,我們可以使我們的模型不那麼複雜,並且我們可以避免過度擬合(使我們的模型不僅學習關鍵的資料特徵,而且學習它的內在噪聲)。

其中一種可能的正則化方法是套索迴歸。當使用套索迴歸時,如果輸入特徵的係數對我們的機器學習模型訓練沒有積極的貢獻,則它們會縮小。這樣,一些特徵可能會被自動丟棄,即將它們的係數指定為零。

from sklearn.linear_model import LassoCV

regr = LassoCV(cv=5, random_state=101)
regr.fit(X_Train,Y_Train)
print("LassoCV Best Alpha Scored: ", regr.alpha_)
print("LassoCV Model Accuracy: ", regr.score(X_Test, Y_Test))
model_coef = pd.Series(regr.coef_, index = list(X.columns[:-1]))
print("Variables Eliminated: ", str(sum(model_coef == 0)))
print("Variables Kept: ", str(sum(model_coef != 0)))

機器學習中特徵選擇怎麼做?這篇文章告訴你

一旦訓練了我們的模型,我們就可以再次建立一個特徵重要性圖來了解哪些特徵被我們的模型認為是最重要的(圖 8)。這是非常有用的,尤其是在試圖理解我們的模型是如何決定做出預測的時候,因此使我們的模型更易於解釋。

figure(num=None, figsize=(12, 10), dpi=80, facecolor='w', edgecolor='k')

top_coef = model_coef.sort_values()
top_coef[top_coef != 0].plot(kind = "barh")
plt.title("Most Important Features Identified using Lasso (!0)")

機器學習中特徵選擇怎麼做?這篇文章告訴你

圖 8:套索特徵重要性圖

via:https://towardsdatascience.com/feature-selection-techniques-1bfab5fe0784

- END -

如果看到這裡,說明你喜歡這篇文章,請轉發、點贊掃描下方二維碼或者微信搜尋「perfect_iscas」,新增好友後即可獲得10套程式設計師全棧課程+1000套PPT和簡歷模板向我私聊「進群」二字即可進入高質量交流群。

掃描二維碼進群↓

機器學習中特徵選擇怎麼做?這篇文章告訴你

機器學習中特徵選擇怎麼做?這篇文章告訴你

機器學習中特徵選擇怎麼做?這篇文章告訴你

在看 機器學習中特徵選擇怎麼做?這篇文章告訴你

相關文章