機器學習教程:帶你從Kaggle入門到殺入前5%(上)

本文由深度學習中文社區(dl.tustcs.com)整理發佈.更多相關資源請見文末.

Introduction

本文整理的是關於參加Kaggle比賽的一些技巧.在 (點擊可閱讀)中將介紹一次進入前5%的經歷,歡迎關注.相關實驗代碼已經上傳至github,關注我頭條號後發送私信"Kaggle"獲取地址.

一次完整的Kaggle比賽的大致流程如下.

1. Data Exploration

在這一步要做的基本就是 EDA (Exploratory Data Analysis),也就是對數據進行探索性的分析,從而為之後的處理和建模提供必要的結論。

通常我們會用 pandas 來載入數據,並做一些簡單的可視化來理解數據。

1.1 Visualization

通常來說 matplotlibseaborn 提供的繪圖功能就可以滿足需求了。

比較常用的圖表有:

  • 查看目標變量的分佈。當分佈不平衡時,根據評分標準和具體模型的使用不同,可能會嚴重影響性能。
  • Numerical Variable,可以用 Box Plot 來直觀地查看它的分佈。
  • 對於座標類數據,可以用 Scatter Plot 來查看它們的分佈趨勢和是否有離群點的存在。
  • 對於分類問題,將數據根據 Label 的不同著不同的顏色繪製出來,這對 Feature 的構造很有幫助。
  • 繪製變量之間兩兩的分佈和相關度圖表。

1.2 Statistical Tests

我們可以對數據進行一些統計上的測試來驗證一些假設的顯著性。雖然大部分情況下靠可視化就能得到比較明確的結論,但有一些定量結果總是更理想的。不過,在實際數據中經常會遇到非 i.i.d. 的分佈。所以要注意測試類型的的選擇和對顯著性的解釋。

在某些比賽中,由於數據分佈比較奇葩或是噪聲過強,Public LB 的分數可能會跟 Local CV 的結果相去甚遠。可以根據一些統計測試的結果來粗略地建立一個閾值,用來衡量一次分數的提高究竟是實質的提高還是由於數據的隨機性導致的。

2. Data Preprocessing

大部分情況下,在構造 Feature 之前,我們需要對比賽提供的數據集進行一些處理。通常的步驟有:

  • 有時數據會分散在幾個不同的文件中,需要 Join 起來。
  • 處理 Missing Data
  • 處理 Outlier
  • 必要時轉換某些 Categorical Variable 的表示方式。
  • 有些 Float 變量可能是從未知的 Int 變量轉換得到的,這個過程中發生精度損失會在數據中產生不必要的 Noise,即兩個數值原本是相同的卻在小數點後某一位開始有不同。這對 Model 可能會產生很負面的影響,需要設法去除或者減弱 Noise。

這一部分的處理策略多半依賴於在前一步中探索數據集所得到的結論以及創建的可視化圖表。在實踐中,我建議使用 iPython Notebook 進行對數據的操作,並熟練掌握常用的 pandas 函數。這樣做的好處是可以隨時得到結果的反饋和進行修改,也方便跟其他人進行交流(在 Data Science 中 Reproducible Results 是很重要的)。

下面給兩個例子。

2.1 Outlier

機器學習教程:帶你從Kaggle入門到殺入前5%(上)

這是經過 Scaling 的座標數據。可以發現右上角存在一些離群點,去除以後分佈比較正常。

2.2 Dummy Variables

對於 Categorical Variable,常用的做法就是 One-hot encoding。即對這一變量創建一組新的偽變量,對應其所有可能的取值。這些變量中只有這條數據對應的取值為 1,其他都為 0。

如下,將原本有 7 種可能取值的 Weekdays 變量轉換成 7 個 Dummy Variables。

機器學習教程:帶你從Kaggle入門到殺入前5%(上)

要注意,當變量可能取值的範圍很大(比如一共有成百上千類)時,這種簡單的方法就不太適用了。這時沒有有一個普適的方法,但我會在下一小節描述其中一種。

3. Feature Engineering

有人總結 Kaggle 比賽是 “Feature 為主,調參和 Ensemble 為輔”,我覺得很有道理。Feature Engineering 能做到什麼程度,取決於對數據領域的瞭解程度。比如在數據包含大量文本的比賽中,常用的 NLP 特徵就是必須的。怎麼構造有用的 Feature,是一個不斷學習和提高的過程。

一般來說,當一個變量從直覺上來說對所要完成的目標有幫助,就可以將其作為 Feature。至於它是否有效,最簡單的方式就是通過圖表來直觀感受。比如:

機器學習教程:帶你從Kaggle入門到殺入前5%(上)

3.1 Feature Selection

總的來說,我們應該生成儘量多的 Feature,相信 Model 能夠挑出最有用的 Feature。但有時先做一遍 Feature Selection 也能帶來一些好處:

  • Feature 越少,訓練越快。
  • 有些 Feature 之間可能存在線性關係,影響 Model 的性能。
  • 通過挑選出最重要的 Feature,可以將它們之間進行各種運算和操作的結果作為新的 Feature,可能帶來意外的提高。

Feature Selection 最實用的方法也就是看 Random Forest 訓練完以後得到的 Feature Importance 了。其他有一些更復雜的算法在理論上更加 Robust,但是缺乏實用高效的實現,比如這個。從原理上來講,增加 Random Forest 中樹的數量可以在一定程度上加強其對於 Noisy Data 的 Robustness。

看 Feature Importance 對於某些數據經過脫敏處理的比賽尤其重要。這可以免得你浪費大把時間在琢磨一個不重要的變量的意義上。

3.2 Feature Encoding

這裡用一個例子來說明在一些情況下 Raw Feature 可能需要經過一些轉換才能起到比較好的效果。

假設有一個 Categorical Variable 一共有幾萬個取值可能,那麼創建 Dummy Variables 的方法就不可行了。這時一個比較好的方法是根據 Feature Importance 或是這些取值本身在數據中的出現頻率,為最重要(比如說前 95% 的 Importance)那些取值(有很大可能只有幾個或是十幾個)創建 Dummy Variables,而所有其他取值都歸到一個“其他”類裡面。

4 Model Selection

準備好 Feature 以後,就可以開始選用一些常見的模型進行訓練了。Kaggle 上最常用的模型基本都是基於樹的模型:

  • Gradient Boosting
  • Random Forest
  • Extra Randomized Trees

以下模型往往在性能上稍遜一籌,但是很適合作為 Ensemble 的 Base Model。這一點之後再詳細解釋。(當然,在跟圖像有關的比賽中神經網絡的重要性還是不能小覷的。)

  • SVM
  • Linear Regression
  • Logistic Regression
  • Neural Networks

以上這些模型基本都可以通過 sklearn 來使用。

當然,這裡不能不提一下 XgboostGradient Boosting 本身優秀的性能加上 Xgboost 高效的實現,使得它在 Kaggle 上廣為使用。幾乎每場比賽的獲獎者都會用 Xgboost 作為最終 Model 的重要組成部分。在實戰中,我們往往會以 Xgboost 為主來建立我們的模型並且驗證 Feature 的有效性。

4.1 Model Training

在訓練時,我們主要希望通過調整參數來得到一個性能不錯的模型。一個模型往往有很多參數,但其中比較重要的一般不會太多。比如對 sklearn 的 RandomForestClassifier 來說,比較重要的就是隨機森林中樹的數量 n_estimators 以及在訓練每棵樹時最多選擇的特徵數量 max_features。所以我們需要對自己使用的模型有足夠的瞭解,知道每個參數對性能的影響是怎樣的

通常我們會通過一個叫做 Grid Search 的過程來確定一組最佳的參數。其實這個過程說白了就是根據給定的參數候選對所有的組合進行暴力搜索。

機器學習教程:帶你從Kaggle入門到殺入前5%(上)

順帶一提,Random Forest 一般在 max_features 設為 Feature 數量的平方根附近得到最佳結果。

這裡要重點講一下 Xgboost 的調參。通常認為對它性能影響較大的參數有:

  • eta:每次迭代完成後更新權重時的步長。越小訓練越慢。
  • num_round:總共迭代的次數。
  • subsample:訓練每棵樹時用來訓練的數據佔全部的比例。用於防止 Overfitting。
  • colsample_bytree:訓練每棵樹時用來訓練的特徵的比例,類似 RandomForestClassifier 的 max_features。
  • max_depth:每棵樹的最大深度限制。與 Random Forest 不同,Gradient Boosting 如果不對深度加以限制,最終是會 Overfit 的
  • early_stopping_rounds:用於控制在 Out Of Sample 的驗證集上連續多少個迭代的分數都沒有提高後就提前終止訓練。用於防止 Overfitting。

一般的調參步驟是:

  1. 將訓練數據的一部分劃出來作為驗證集。
  2. 先將 eta 設得比較高(比如 0.1),num_round 設為 300 ~ 500。
  3. 用 Grid Search 對其他參數進行搜索
  4. 逐步將 eta 降低,找到最佳值。
  5. 以驗證集為 watchlist,用找到的最佳參數組合重新在訓練集上訓練。注意觀察算法的輸出,看每次迭代後在驗證集上分數的變化情況,從而得到最佳的 early_stopping_rounds。
機器學習教程:帶你從Kaggle入門到殺入前5%(上)

最後要提一點,所有具有隨機性的 Model 一般都會有一個 seed 或是 random_state 參數用於控制隨機種子。得到一個好的 Model 後,在記錄參數時務必也記錄下這個值,從而能夠在之後重現 Model。

4.2 Cross Validation

Cross Validation 是非常重要的一個環節。它讓你知道你的 Model 有沒有 Overfit,是不是真的能夠 Generalize 到測試集上。在很多比賽中 Public LB 都會因為這樣那樣的原因而不可靠。當你改進了 Feature 或是 Model 得到了一個更高的

CV 結果,提交之後得到的 LB 結果卻變差了,一般認為這時應該相信 CV 的結果。當然,最理想的情況是多種不同的 CV 方法得到的結果和 LB 同時提高,但這樣的比賽並不是太多。

在數據的分佈比較隨機均衡的情況下,5-Fold CV 一般就足夠了。如果不放心,可以提到 10-Fold但是 Fold 越多訓練也就會越慢,需要根據實際情況進行取捨。

很多時候簡單的 CV 得到的分數會不大靠譜,Kaggle 上也有很多關於如何做 CV 的討論。比如這個。但總的來說,靠譜的 CV 方法是 Case By Case 的,需要在實際比賽中進行嘗試和學習,這裡就不再(也不能)敘述了。

5. Ensemble Generation

Ensemble Learning 是指將多個不同的 Base Model 組合成一個 Ensemble Model 的方法。它可以同時降低最終模型的 Bias 和 Variance(證明可以參考這篇論文,我最近在研究類似的理論,可能之後會寫新文章詳述),從而在提高分數的同時又降低 Overfitting 的風險。在現在的 Kaggle 比賽中要不用 Ensemble 就拿到獎金幾乎是不可能的。

常見的 Ensemble 方法有這麼幾種:

  • Bagging:使用訓練數據的不同隨機子集來訓練每個 Base Model,最後進行每個 Base Model 權重相同的 Vote。也即 Random Forest 的原理。
  • Boosting:迭代地訓練 Base Model,每次根據上一個迭代中預測錯誤的情況修改訓練樣本的權重。也即 Gradient Boosting 的原理。比 Bagging 效果好,但更容易 Overfit。
  • Blending:用不相交的數據訓練不同的 Base Model,將它們的輸出取(加權)平均。實現簡單,但對訓練數據利用少了。
  • Stacking:接下來會詳細介紹。

從理論上講,Ensemble 要成功,有兩個要素:

  • Base Model 之間的相關性要儘可能的小。
    這就是為什麼非 Tree-based Model 往往表現不是最好但還是要將它們包括在 Ensemble 裡面的原因。Ensemble 的 Diversity 越大,最終 Model 的 Bias 就越低。
  • Base Model 之間的性能表現不能差距太大。這其實是一個 Trade-off,在實際中很有可能表現相近的 Model 只有寥寥幾個而且它們之間相關性還不低。但是實踐告訴我們即使在這種情況下 Ensemble 還是能大幅提高成績。

5.1 Stacking

相比 Blending,Stacking 能更好地利用訓練數據。以 5-Fold Stacking 為例,它的基本原理如圖所示:

機器學習教程:帶你從Kaggle入門到殺入前5%(上)

整個過程很像 Cross Validation。首先將訓練數據分為 5 份,接下來一共 5 個迭代,每次迭代時,將 4 份數據作為 Training Set 對每個 Base Model 進行訓練,然後在剩下一份 Hold-out Set 上進行預測。同時也要將其在測試數據上的預測保存下來。這樣,每個 Base Model 在每次迭代時會對訓練數據的其中 1 份做出預測,對測試數據的全部做出預測。5 個迭代都完成以後我們就獲得了一個 #訓練數據行數 x #Base Model 數量 的矩陣,這個矩陣接下來就作為第二層的 Model 的訓練數據。當第二層的 Model 訓練完以後,將之前保存的 Base Model 對測試數據的預測(因為每個 Base Model 被訓練了 5 次,對測試數據的全體做了 5 次預測,所以對這 5 次求一個平均值,從而得到一個形狀與第二層訓練數據相同的矩陣)拿出來讓它進行預測,就得到最後的輸出。

這裡給出我的實現代碼:

機器學習教程:帶你從Kaggle入門到殺入前5%(上)

獲獎選手往往會使用比這複雜得多的 Ensemble,會出現三層、四層甚至五層,不同的層數之間有各種交互,還有將經過不同的 Preprocessing 和不同的 Feature Engineering 的數據用 Ensemble 組合起來的做法。但對於新手來說,穩穩當當地實現一個正確的 5-Fold Stacking 已經足夠了。

6. Pipeline

可以看出 Kaggle 比賽的 Workflow 還是比較複雜的。尤其是 Model Selection 和 Ensemble。理想情況下,我們需要搭建一個高自動化的 Pipeline,它可以做到:

  • 模塊化 Feature Transform,只需寫很少的代碼就能將新的 Feature 更新到訓練集中。
  • 自動化 Grid Search,只要預先設定好使用的 Model 和參數的候選,就能自動搜索並記錄最佳的 Model。
  • 自動化 Ensemble Generation,每個一段時間將現有最好的 K 個 Model 拿來做 Ensemble。

對新手來說,第一點可能意義還不是太大,因為 Feature 的數量總是人腦管理的過來的;第三點問題也不大,因為往往就是在最後做幾次 Ensemble。但是第二點還是很有意義的,手工記錄每個 Model 的表現不僅浪費時間而且容易產生混亂。

Crowdflower Search Results Relevance 的第一名獲得者 Chenglong Chen 將他在比賽中使用的 Pipeline 公開了,非常具有參考和借鑑意義。只不過看懂他的代碼並將其中的邏輯抽離出來搭建這樣一個框架,還是比較困難的一件事。可能在參加過幾次比賽以後專門抽時間出來做會比較好。

機器學習教程:帶你從Kaggle入門到殺入前5%(上)

在 (點擊可閱讀)中將會介紹結合以上內容參加Kaggle比賽的全過程,歡迎大家關注.

相關實驗代碼已經上傳至github,關注我頭條號後發送私信"Kaggle"獲取地址.


分享到:


相關文章: