kaggle比賽流程(轉)

kaggle比賽流程(轉)

一、比賽概述

  • 不同比賽有不同的任務,分類、迴歸、推薦、排序等。比賽開始後訓練集和測試集就會開放下載。
  • 比賽通常持續 2 ~ 3 個月,每個隊伍每天可以提交的次數有限,通常爲 5 次。
  • 比賽結束前一週是一個 Deadline,在這之後不能再組隊,也不能再新加入比賽。所以想要參加比賽請務必在這一 Deadline 之前有過至少一次有效的提交
  • 一般情況下在提交後會立刻得到得分的反饋。不同比賽會採取不同的評分基準,可以在分數欄最上方看到使用的評分方法。
  • 反饋的分數是基於測試集的一部分計算的,剩下的另一部分會被用於計算最終的結果。所以最後排名會變動。
  • LB 指的就是在 Leaderboard 得到的分數,由上,有 Public LB 和 Private LB 之分。
  • 自己做的 Cross Validation 得到的分數一般稱爲 CV 或是 Local CV。一般來說 CV 的結果比 LB 要可靠

二、可視化

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

比較常用的圖表有:

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

三、數據處理

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

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

這一部分的處理策略多半依賴於在前一步中探索數據集所得到的結論以及創建的可視化圖表。在實踐中,我建議使用 iPython Notebook 進行對數據的操作,並熟練掌握常用的 pandas 函數。

四、特徵工程

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

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

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

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

 

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

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

 

五、模型選擇

準備好 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 的有效性。順帶一提,在 Windows 上安裝 Xgboost 很容易遇到問題,目前已知最簡單、成功率最高的方案可以參考我在這篇帖子中的描述

 

六、模型訓練

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

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

1
2
3
param_grid = {'n_estimators': [300, 500], 'max_features': [10, 12, 14]}
model = grid_search.GridSearchCV(estimator=rfr, param_grid=param_grid, n_jobs=1, cv=10, verbose=20, scoring=RMSE)
model.fit(X_train, y_train)

順帶一提,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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
X_dtrain, X_deval, y_dtrain, y_deval = cross_validation.train_test_split(X_train, y_train, random_state=1026, test_size=0.3)
dtrain = xgb.DMatrix(X_dtrain, y_dtrain)
deval = xgb.DMatrix(X_deval, y_deval)
watchlist = [(deval, 'eval')]
params = {
    'booster': 'gbtree',
    'objective': 'reg:linear',
    'subsample': 0.8,
    'colsample_bytree': 0.85,
    'eta': 0.05,
    'max_depth': 7,
    'seed': 2016,
    'silent': 0,
    'eval_metric': 'rmse'
}
clf = xgb.train(params, dtrain, 500, watchlist, early_stopping_rounds=50)
pred = clf.predict(xgb.DMatrix(df_test))

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

七、交叉驗證

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 的,需要在實際比賽中進行嘗試和學習,這裏就不再(也不能)敘述了。

 

八、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 還是能大幅提高成績。

九、Stacking

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

Stacking

整個過程很像 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 次求一個平均值,從而得到一個形狀與第二層訓練數據相同的矩陣)拿出來讓它進行預測,就得到最後的輸出。

這裏給出我的實現代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Ensemble(object):
    def __init__(self, n_folds, stacker, base_models):
        self.n_folds = n_folds
        self.stacker = stacker
        self.base_models = base_models

    def fit_predict(self, X, y, T):
        X = np.array(X)
        y = np.array(y)
        T = np.array(T)

        folds = list(KFold(len(y), n_folds=self.n_folds, shuffle=True, random_state=2016))

        S_train = np.zeros((X.shape[0], len(self.base_models)))
        S_test = np.zeros((T.shape[0], len(self.base_models)))

        for i, clf in enumerate(self.base_models):
            S_test_i = np.zeros((T.shape[0], len(folds)))

            for j, (train_idx, test_idx) in enumerate(folds):
                X_train = X[train_idx]
                y_train = y[train_idx]
                X_holdout = X[test_idx]
                # y_holdout = y[test_idx]
                clf.fit(X_train, y_train)
                y_pred = clf.predict(X_holdout)[:]
                S_train[test_idx, i] = y_pred
                S_test_i[:, j] = clf.predict(T)[:]

            S_test[:, i] = S_test_i.mean(1)

        self.stacker.fit(S_train, y)
        y_pred = self.stacker.predict(S_test)[:]
        return y_pred

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

十、Pipeline

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

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

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

原文:http://www.cnblogs.com/zhizhan/p/5826089.html

分類: kaggle

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章