HyperparameterHunter 3.0:一文教你學會自動化特徵工程

機器之心發表於2019-08-27

歡迎使用 HyperparameterHunter 3.0。

Github地址:https://github.com/HunterMcGushion/hyperparameter_hunter

這一工具可以自動儲存和最佳化特徵工程步驟以及引數,讓最佳化更加智慧,並保證不浪費任何實驗。

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

特徵工程適應到引數最佳化的 Pre-HyperparameterHunter demo

漫長的等待已經結束。HyperparameterHunter 3.0 (Artemis) 來了,它增加了對特徵工程的支援,以下是一些新的特性。

  • 使特徵工程的語法清晰化、可定製的函式列表。

  • 構建特徵工程工作流的一致性框架,流程自動記錄。

  • 特徵工程步驟最佳化,包括對過去實驗的檢測,以進行快速啟動最佳化。

  • 別再跟蹤特徵工程步驟的列表,以及它們與其他引數一起工作的方式

背景

什麼是特徵工程

很多人對特徵工程和預處理都有不同的定義,那麼 HyperparameterHunter 是如何定義它的呢?

特徵工程」是在模型訓練之前對資料所做的任何修改——無論是在實驗開始的時候所做的一次修改,還是在在每一輪交叉驗證時所做的重複修改。從技術上講,HyperparameterHunter 可以讓使用者自定義「特徵工程」的細節。下面是「特徵工程」定義下的一些可能的方法:

  • 手動特徵建立

  • 縮放/歸一化/標準化 

  • 重取樣 (參考我們的 imblearn 的例子)

  • 目標資料轉換

  • 特徵選擇/消除

  • 編碼(one-hot,標籤等等)

  • 填補

  • 二值化/合併/離散化

還有其他相關的資料操作。

為什麼應該關心特徵工程

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

特徵工程很少成為引數最佳化中的一個話題。所以為什麼要關係它呢?

首先,特徵工程是很重要的。

你幾乎總是需要預處理你的資料。這是一個必須的步驟。

其次,特徵工程引數調參是一樣的,只不過引數可以手動調整。

在資料建模前,我們會遇到很多特徵工程上的問題,比如說,應該使用 StandardScaler 還是 Normalizer?我們只能對這兩者進行測試,嘗試記住哪種對演算法是最好的。相似的問題還有:應該使用 one-hot 來編碼每週的日期嗎?或者還是使用「是否是週末」的二值編碼?需要考慮月份嗎?年份呢?應該將十二個月轉換成四季嗎?閏年該怎麼辦?

但是歸根接地,開發者所用的眾多特徵工程中實際上只是另一種需要最佳化的引數而已——但是並沒有工具去最佳化這些「引數』,為什麼呢?

這裡有一個很好的理由:特徵工程很難。它並不是在 0.1 到 0.7 之間挑一個數字,或者是選擇使用 sigmoid 還是 ReLU 作為神經網路層的啟用函式。這裡討論的是將資料處理的方式引數化,並最佳化一系列功能。這需要我們知道每個特徵代表著什麼,以及引數化後返回了什麼結果——所有的這一切都是在轉換寶貴的資料。

現在的特徵過程可能是這樣的:拼湊一個指令碼檔案去進行所有的特徵工程,然後將這個指令碼拖拽到其他專案中去。對於每個不同的專案粗暴地刪除或者修改需要的部分。如果這樣做的話,在專案結束的時候不可能重新建立所有的實驗,因為實驗中應用的特徵工程沒有清晰的、自動的記錄。

此外,忽略特徵工程會導致引數最佳化結果不可信。確定地說,必須要有一個更好的方法,而現在,有了!

HyperparameterHunter 的方法

在介紹 HyperparameterHunter 如何自動化特徵工程之前。我們首先看一下資料,然後提煉出特徵工程的步驟。資料集是 SKLearn 的波士頓房價迴歸資料集。這個資料集具有可管理的 506 個樣本,除了目標之外還有 13 個特徵。

資料集地址:https://scikit-learn.org/stable/datasets/index.html#boston-house-prices-dataset

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

基線模型

特徵工程的目的是產生更好的模型,首先建立一個基線 CVExperiment,然後透過特徵工程的方式逐漸提升模型的效果。和往常一樣,首先設定環境來定義任務,以及評價結果的方法。

基線CVExperiment地址:https://hyperparameter-hunter.readthedocs.io/en/latest/api_essentials.html#experiment-execution

我們對 5 份資料做 K 重的交叉驗證,只關注在絕對誤差的中間值上。

此外,透過 SKLearn 的 train_test_split 函式可以從 train_dataset 提取出一個 holdout_dataset。

然後使用 AdaBoostRegressor 和它的預設引數執行一個簡單的 CVExperiment 模型,這樣可以看到沒有特徵工程時的結果。

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

定義問題

現在已經建立了 0.51 的基線 MAE 用於 out-of-fold 預測,現在可以看一下用來超越這個基線的一些特徵工程步驟。

A. 建立人工特徵

因為人類是創造性的,我們喜歡使用特徵工程做一些有趣的事情,所以可以把自定義的特徵新增到輸入資料中,首先,可以建立一個特徵,它是由 13 個其他特徵得到的歐幾里得範數,或者我們可以定義ℓ2-norm!本著創新的精神,本文將歐幾里得範數創新性地命名為 euclidean_norm

B. 輸入縮放

接下來要進行一下輸入縮放。認真地講,對資料進行縮放通常是一個好主意。

別忘了對 train_inputs 做一下 fit_transform,但是隻對的 non_train_inputs(validation/holdout data)做一下 transform,這樣做是為了避免資料洩露(https://machinelearningmastery.com/data-leakage-machine-learning/)。

C. 目標轉換

特徵工程的最後一步是使用 SKLearn 的 QuantileTransformer 讓目標輸出均勻地分佈,從而讓最頻繁出現的值分散開,並異常值的影響。與我們的輸入縮放一樣,僅僅對 train_targets 進行 fit_transform,然後只 transform 的 non_train_targets。

上手 HyperparameterHunter

好了,別再拖延。如何在 HyperparameterHunter 中完成這些吧。

但是,Hunter 中定義特徵工程步驟的語法是如此的順暢和合乎邏輯!我從來沒想過 HyperparameterHunter 會以我早在使用的格式期待它們!真是太瘋狂了!但是那又如何呢???

—你(也許你會這麼說)

好了,親愛的讀者,秘密的成分就是上面寫到的那些函式,尤其是那些輸入的引數命令。我麼將這些函式叫做 EngineerStep 函式,因為每個函式都是一個工程步驟。一個 FeatureEngineer 在這裡僅僅是一個 EngineerSteps 的列表或者函式。

回到秘密成分上。一個 EngineerStep 函式僅僅是一個普通的函式,你可以在其中做任何你想做的資料處理。只需要在輸入引數中告知想要處理的資料就行。精明的讀者或許已經注意到了上面提到的 EngineerStep 函式的模式,但是為了記住合規的 EngineerStep 函式引數,這裡有一個有效的公式。

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

從第一個集合中拿一個字串,將第二個集合中的一個字串連線在它後面,然後你就得到了一個合規的 EngineerStep 函式引數。另一個重要的部分就是函式返回的結果。幸好這個更加容易記住。返回的是函式的新值。你還可以選擇返回變換器來執行逆目標變換,就像我們上面的 quantile_transform 一樣。

還有兩個別名來組合資料以便於處理,我們已在上面的函式中使用過這些別名了。讓我們更新一下這個高度複雜和細緻入微的公式,以新增額外的 EngineerStep 函式引數別名:

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

正如新引數的名稱所暗示的那樣,「all_inputs」/「all_targets」為你提供了所有資料集輸入/目標的大型 DataFrame。「non_train_inputs」和「non_train_targets」類似,只是它們省略了所有訓練資料。每個公式下面的註釋都提醒「test_inputs」沒有目標對應引數,因為我們不按設計跟蹤測試目標。

進一步瞭解

有了對如何建立特徵工程步驟的新認識,現在開始在 CVExperiment 中使用特徵工程吧。

在 CVExperiment 中僅僅需要 feature_engineer kwarg,或者任何 OptPro 的 forge_experiment 方法。feature_engineer 可以是一個 FeatureEngineer 例項,或者是 EngineerSteps/函式的列表,就像我們上面定義過的那些一樣。

hyperparameter_hunter package地址:https://hyperparameter-hunter.readthedocs.io/en/latest/source/hyperparameter_hunter.html#hyperparameter_hunter.EngineerStep

實驗部分

還記得基線在 OOF 資料上達到了中位數為 0.51 的絕對誤差中值嗎。現在可以用一些 FeatureEngineer 增強的 CVExperiments 模型做一些測試,看看會發生什麼...

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

讓我們分析一下發生了什麼。三個不同的 CVExperiment,每個都使用了不同的 FeatureEngineer,實驗 #1 和基線實驗的效能一樣。實驗 #2 稍微好一些。實驗 #3 說明誤差從 0.51 降到 0.46。或許現在可以說 quantile_transform 就是最好的特徵工程步驟,然後就完事了。但是我們如何能夠確定呢?

首先面對的是最佳化

在 CVExperiment 中使用 FeatureEngineer 是非常棒的。讓 HyperparameterHunter 的 OptPros 來為測試特徵工程步驟的不同組合甚至會有更好的效果。

讀者可能會擔心,增加最佳化步驟必然會使特徵工程複雜化。但是不必擔心,因為僅僅需要使用 OptPros 的 forge_experiment 方法,這就像在初始化一個 CVExperiment。

為了在不同 EngineerSteps 組成的空間內進行搜尋,只需將這些步驟放在 Categorical 內部,像是標準的引數最佳化一樣。想嘗試一個特別值得懷疑的 EngineerStep 時,Categorical 也有一個可選擇的 kwarg。如果 optional = True(預設值= False),則搜尋空間不僅包括顯式給出的 Categorical,還包括完全省略當前的 EngineerStep。

在做特徵最佳化之前,需要更多的 EngineerStep 函式來做最佳化。也許讀者希望嘗試一些 standard_scale 之外的其他的縮放方法。我們可以先來先定義一下 min_max_scale 和 normalize 的相關方法。

請注意,在經典的 HyperparameterHunter 中,我 OptPro 會自動發現上面的 4 個實驗與我們的搜尋空間是相容的,並且將它們作為學習材料來實現快速啟動最佳化。

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

藍色矩形中新增了透過 OptPro 實現的一些新實驗的分數。

每當 OptPros 發現一個實驗具有比當前最好的結果更高的分數,它就會將這個得分標為粉紅色,將它的引數標為綠色。透過 16 次實驗,OptPro 只是剛剛預熱,但 quantile_transform 看起來很有希望。此外,似乎嘗試一些不同的縮放器可能會得到更好的結果,畢竟我們新的最佳實驗使用最近新增的 min_max_scale 方法,而不是 standard_scale。

回到源頭

現在,讓我們回到我們的根源。我們希望把我們新的特徵最佳化技術和一些經典的引數最佳化混合起來,因為沒人願意陷在區域性最優裡面。

除了增加經典的引數最佳化之外,讓我們假裝自信一些——euclidean_norm 是重要的 (儘管它實際上似乎並非如此),透過刪除包含它的 Categorical,讓它變成一個必需的 EngineerStep。請注意,這個變化意味著我們的 OptPro 將會僅僅從 16 個候選實驗中的 8 個已經儲存的實驗中學習,因為我們限制了搜尋空間。

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

quantile_transform 繼續執行沒有目標的轉換,但是讓我們在 power_transform 中新增一些真正的競爭。

我們還可以透過把 BayesianOptPro 切換成 RandomForestOptPro(或者任何其他的 OptPro)來得到另一種觀點。看一下我們上面的實驗,貌似 normalize 並不是做得十分好,所以我們放棄它吧。實際上,讓我們假設,確定想要的是 standard_scale 或者 min_max_scale,所以我們將會從這種混合中刪除 normalize,並在我們的第二個 EngineerStep 中刪除 optional=True 的部分。

因為我們有些過於熱情的決定 euclidean_norm 很重要的一件事,所以讓我們再次選擇第一個 EngineerStep 吧。當然,我們還需要新增 power_transform 作為我麼最後一個 EngineerStep 的選擇。

總之,下面的 OptPro 將會修改上面的三個 EngineerSteps,作為一種改變,我們將會嘗試 RandomForestOptPro。

HyperparameterHunter 3.0:一文教你學會自動化特徵工程

儘管改變了整個 FeatureEngineer 的空間,甚至需要一個新的 OptPro 來執行整個過程,我們還是能夠從 26 個儲存的候選者中識別出 16 個匹配的實驗,這些實驗可以用作跳躍式最佳化。可以說,這要比開始的時候好很多。

更好的是,我們有一個新的最佳實驗了,它將結果提升到了 0.37 的 MAE,沒有做任何的特徵工程,從基線的 0.51 上降了下來。

現在,你這隻美麗的孔雀,起飛吧!

這些結果的神奇之處就是它們都會儲存在你計算機本地,這意味著你可以持續使用好多天、好幾星期、好幾年,甚至好幾代人。好了,也許這不是最後一部分。

關鍵在於當你從這個小問題開始,朝著構建一個需要訓練好多時間的模型開始的時候,你為何要滿足於重新執行相同的模型呢?或者從過去的實驗中攫取有價值的資訊,或者手動地追蹤所有這些荒謬的引數特徵工程呢?

展開你的翅膀,讓 HyperparameterHunter 來處理這些煩人的瑣事吧,這樣你就可以不再去跟蹤這一切了,可以將你的時間花在機器學習上了。

原文連結:https://towardsdatascience.com/hyperparameter-hunter-feature-engineering-958966818b6e

相關文章