機器學習小竅門:Python 幫你進行特徵選擇

 2018-07-25 17:01:00.0

原標題 A Feature Selection Tool for Machine Learning in Python,作者爲 William Koehrsen。


特徵選擇,也就是從數據集中找出並選擇最有用特徵的過程,是機器學習工作流中一個非常重要的步驟。不必要的特徵降低了訓練速度,降低了模型的可解釋性,最重要的是降低了測試數據集的泛化能力。

在做機器學習問題的過程中,我們總是在重複應用一些特徵選擇方法,這很令人沮喪。因此我用 Python 建了一個特徵選擇類,代碼已上傳至 GitHub。這個 FeatureSelector 包含一些通用的特徵選擇方法:

  1. 缺失值比例高的特徵 

  2. 共線 (高相關)特徵 

  3. 決策樹中的零貢獻度特徵 

  4. 低貢獻度特徵 

  5. 單值特徵 

本文將通過一個機器學習數據集例子來展示如何使用 FeatureSelector。可以看到該工具如何快速實現這些方法,讓機器學習工作流更高效。 

完整的代碼可在 GitHub 上找到,歡迎各位任何形式的貢獻。特徵選擇器在不斷改進,它將根據社區的需要不斷修正和完善!


樣例數據集

本文將使用 Kaggle 的 Home Credit Default Risk 機器學習競賽裏的樣本數據。(想參加比賽的可以看這篇文章)。 完整的數據集可以在此處下載, 本文將使用樣本做演示用。

機器學習小竅門:Python 幫你進行特徵選擇

樣本數據。TARGET 爲分類標籤

競賽是一個監督分類問題。這是一個非常合適的數據集,因爲它有很多缺失值、大量高度相關(共線)的特徵以及許多無助於機器學習建模的不相關特徵。

機器學習小竅門:Python 幫你進行特徵選擇


建立實例

爲了建立一個 FeatureSelector 類的實例,我們需要輸入一個結構化的數據集,其中行記錄觀測結果,列記錄特徵。有些方法中我們可以只使用特徵來學習,但另外一些重要的方法也需要標籤。由於這是一個監督分類的任務,我們會同時用到特徵和標籤。

(在 feature_selector.py 所在目錄中執行以下代碼)

機器學習小竅門:Python 幫你進行特徵選擇


方法說明

特徵選擇供有 5 個方法來找到需要剔除的特徵。我們可以訪問任意標識出的特徵然後手工從數據集中剔除它們,或用特徵選擇器裏的 remove 方法。 

本文將依次瀏覽這些定位特徵的方法,並展示如何一次性執行這些方法。此外 FeatureSelector 還有一些繪圖功能,因爲在機器學習中可視化數據是非常關鍵的。


缺失值

第一個找到需要被剔除的特徵的方法非常直接:缺失值比率超過指定閾值。以下代碼可以定位出所有缺失值比例超過 60% 的特徵(粗體爲輸出內容)。

機器學習小竅門:Python 幫你進行特徵選擇

我們可以從 dataframe 看到這些特徵的缺失值比例:

機器學習小竅門:Python 幫你進行特徵選擇

機器學習小竅門:Python 幫你進行特徵選擇

可以訪問 FeatureSelector 裏的 ops 屬性來看到這些被標記移除的特徵。它存儲爲一個 Python dict,其中每一項以 list 形式存儲特徵名稱。

機器學習小竅門:Python 幫你進行特徵選擇

最後,用以下命令繪製一下所有特徵缺失值比例的分佈情況:

機器學習小竅門:Python 幫你進行特徵選擇

機器學習小竅門:Python 幫你進行特徵選擇


共線特徵

共線特徵也就是那些互相之間高度相關的特徵。由於其較高的方差和較低的可解釋性,它們將導致測試集數據泛化能力變差。 

identify_collinear 方法基於指定的相關係數值,找到那些共線特徵。對於每對相關的特徵,程序識別出其中一個特徵,並剔除它(因爲只需要剔除其中一個):

機器學習小竅門:Python 幫你進行特徵選擇

可以用熱力圖簡潔地可視化特徵的相關性。圖中顯示了所有至少與一個特徵的相關係數大於閾值的特徵: fs.plot_collinear() 與之前方式類似,

機器學習小竅門:Python 幫你進行特徵選擇

機器學習小竅門:Python 幫你進行特徵選擇

在此之前,我們可通過 ops 字典訪問整個高相關度的(將被剔除的)特徵列表, 也可用 dataframe 方式查看那些高度相關的特徵對。

機器學習小竅門:Python 幫你進行特徵選擇

機器學習小竅門:Python 幫你進行特徵選擇

 如果想直接瞭解整個數據集,我們也可以繪製數據集中所有特徵的相關係數熱力圖。只要在方法中傳入 plot_all = True:

機器學習小竅門:Python 幫你進行特徵選擇


零重要度特徵 

前面兩種方法可以用於任何結構的數據集。並且在給定閾值下,任何時候得到的結果都是一樣的。接下來一種方法適用於有監督的機器學習。我們必須有用於訓練的標籤,結果也是不一定的。identify_zero_importance 函數根據 GBM 學習模型找到零重要度特徵。

通過基於樹的機器學習模型,比如 Boosting 集成方法,我們可以找到特徵重要度。重要度的絕對值沒有相對值重要。通過相對值,我們可以決定與任務相關性最強的特徵。我們也可以使用特徵重要度,去除零重要度特徵完成特徵選擇。在基於樹的模型中我們並不使用零重要度特徵來分割各點,所以我們可以將它們去除而不影響模型性能。 

FeatureSelector 使用 GBM 從 LightGBM library 中找到特徵重要度。運行 10 次以上 GBM 求平均得到特徵重要性,從而減少方差。同時,模型使用驗證集的 early stopping(有關閉選項),避免訓練數據的過擬合。 

下面的代碼調用這種方法,輸出零重要度特徵:

機器學習小竅門:Python 幫你進行特徵選擇

輸入參數:

  • task: 任務是「分類」或是「迴歸」 

  • eval_metric:用於 early stopping 的矩陣 (如果禁用 early stopping,這項不是必須) 

  • n_iterations:用於求特徵重要性平均值的訓練運行次數 

  • early_stopping:是否將 early stopping 用於模型訓練 

這時使用 plot_feature_importances 得到兩張曲線圖:

機器學習小竅門:Python 幫你進行特徵選擇

機器學習小竅門:Python 幫你進行特徵選擇

機器學習小竅門:Python 幫你進行特徵選擇

左邊的 plot_n 是最重要特徵(畫出了重要性的歸一化項,它們的和爲 1)。右邊的是累計的重要性相對於特徵的個數,縱軸是累計重要度的 threshold。這個例子中是 99%。

對於基於重要度的方法,以下兩點需要記住: 

  • GBM 的訓練具有隨機性,也就是說每次運行模型得到的特徵重要度都是不同的 

這不應成爲主要的問題(最重要的特徵不會突然變成最不重要的),但它會改變一些特徵的排序。它也可能影響到識別出的零重要度特徵數。你並不需要對特徵重要度每次變化的問題感到吃驚。

  • 爲了訓練機器學習模型,首先將特徵進行獨熱編碼。這就意味着在建模時加入的獨熱編碼的特徵可能是一些被識別爲零重要度的特徵

在特徵去除階段有去除任何獨熱編碼特徵的選項,然而如果在特徵選擇之後進行機器學習,我們必須對特徵進行獨熱編碼。


低重要度特徵 

接下來的方法建立在零重要度函數上,它使用模型的特徵重要度來進行之後的選擇。identify_low_importance 函數找到最低重要度的特徵,這些特徵對特定的總重要度沒有任何貢獻。 

例如,下面的調用函數找到最低重要度的特徵。它並不需要達到 99% 的總重要度: 

機器學習小竅門:Python 幫你進行特徵選擇

基於總重要度及這些信息的曲線,GBM 將很多特徵判斷爲與學習無關。這種方法每次訓練得到的結果並不相同。 

在 dataframe 中查看特徵重要度: 

機器學習小竅門:Python 幫你進行特徵選擇

機器學習小竅門:Python 幫你進行特徵選擇

low_importance 方法來源於一種使用主成分分析(PCA)的方法。它通常只保留所需的主成分以將方差百分比保持在特定值上(比如 95%)。總重要度的百分比的計算也是基於這個想法。 

這種基於特徵重要度的方法只在使用基於樹的模型做預測時有用。除了具有隨機性之外,這種基於重要度的方法是一個黑盒子。我們並不知道模型爲什麼將某種特徵判斷爲無關。如果使用這些方法,將它們運行幾次並觀察結果如何變化。創建多個不同參數的數據集進行測試。


唯一值特徵

最後一個是很基礎的一種方法:找到任何有單一值的列。一個只有唯一值的特徵無法用於機器學習,因爲這個特徵的方差爲 0。比如,一個基於樹的模型無法在只有一個值的特徵上進行劃分 (因爲不能將觀察對象分組)。

與其他方法不同,這裏沒有參數可以選擇: 

機器學習小竅門:Python 幫你進行特徵選擇

我們可以畫出每個分類唯一值的柱狀圖:

機器學習小竅門:Python 幫你進行特徵選擇

機器學習小竅門:Python 幫你進行特徵選擇

 需要記住的一點是默認在 Pandas 中計算唯一值之前先去掉非數元素(NaNs)。


去除特徵 

一旦我們識別出需要去掉的特徵,我們有兩個選項來去掉它們。所有需要去掉的特徵都存儲在 FeatureSelector 的字典 ops 當中。我們可以使用這個清單來手動去掉這些特徵,另一個選項是使用 remove 的內建函數。 

使用這種方法,我們使用 methods 來去掉特徵。如果我們希望使用所有方法,我們只需要在函數中放入 methods = 'all'。

機器學習小竅門:Python 幫你進行特徵選擇

通過這種方法返回一個已經去除了特徵的 datafram,同時也去除了在機器學習過程中創建的獨熱編碼特徵:

機器學習小竅門:Python 幫你進行特徵選擇

在進一步操作之前,先檢查將要被去除的特徵是一個好主意!原始的數據集被作爲備份存儲在 FeatureSelector 的 data 特性中。


一次運行所有方法

比起單獨運行這些方法,我們可以使用 identify_all 來運行所有的方法。它爲每種方法建立了一個參數字典:

機器學習小竅門:Python 幫你進行特徵選擇

由於我們重新運行了模型,你需要注意到總特徵的個數將會變化,然後就可以調用 remove 函數來去除特徵。


結論 

在訓練機器學習模型之前,Feature Selector 類會執行一些常用操作來去除特徵。它提供識別特徵並去除的函數,並將之可視化。爲了提高工作效率,可以單獨或一次運行所有方法。 

missing,collinear和 single_unique 方法結果是確定的。而基於特徵重要度的方法每次運行的結果都會變化。特徵選擇和機器學習很像,它們都需要大量經驗,需要測試多種組合來找到最優答案。最好是在過程中嘗試多種配置,特徵選擇器提供一種方法快速評估特徵選擇的參數。 

和往常一樣,歡迎各位提出反饋和建設性的意見。我想強調,我正在 FeatureSelector 尋求幫助。任何人都可以在 GitHub 上做出貢獻。對所有使用這個工具並提出的建議的人表示感謝!也可以通過推特 @koehrsen_will 和我聯繫。 


原文鏈接:https://towardsdatascience.com/a-feature-selection-tool-for-machine-learning-in-python-b64dd23710f0


文章來源:雷鋒網