模型融合方法介紹

1 Voting

投票制即為,投票多者為最終的結果。例如一個分類問題,多個模型投票(當然可以設置權重)。最終投票數最多的類為最終被預測的類。

2 Averaging

Averaging即所有預測器的結果平均。

  • 迴歸問題,直接取平均值作為最終的預測值。(也可以使用加權平均)
  • 分類問題,直接將模型的預測概率做平均。(or 加權)

加權平均,其公式如下:

模型融合方法介紹

其中n表示模型的個數, Weighti表示該模型權重,Pi表示模型i的預測概率值。

例如兩個分類器,XGBoost(權重0.4)和LightGBM(權重0.6),其預測概率分別為:0.75、0.5,那麼最終的預測概率,(0.4 * 0.75+0.6 * 0.5)/(0.4+0.6)=0.6

模型權重也可以通過機器學習模型學習得到。

3 Ranking

Rank的思想其實和Averaging一致,但Rank是把排名做平均,對於AUC指標比較有效。

個人認為其實就是Learning to rank的思想,可以來優化搜索排名。具體公式如下:

模型融合方法介紹

其中n表示模型的個數, Weighti表示該模型權重,所有權重相同表示平均融合。Ranki表示樣本在第i個模型中的升序排名。它可以較快的利用排名融合多個模型之間的差異,而不需要加權融合概率。

4 Binning

將單個模型的輸出放到一個桶中。參考pdf paper , Guocong Song ,

5 Bagging

使用訓練數據的不同隨機子集來訓練每個Base Model,最後每個Base Model 權重相同,分類問題進行投票,迴歸問題平均。

隨機森林就用到了Bagging,並且具有天然的並行性。

6 Boosting

Boosting是一種迭代的方法,每一次訓練會更關心上一次被分錯的樣本,比如改變被錯分的樣本的權重的Adaboost方法。還有許多都是基於這種思想,比如Gradient Boosting等。

經典問題:隨機森林、Adaboost、GBDT、XGBoost的區別是什麼?

7 Stacking

模型融合方法介紹

從上圖可以看出,類似交叉驗證。

  1. 將數據集分為K個部分,共有n個模型。
  2. for i in xrange(n):
  3. for i in xrange(k):
  4. 用第i個部分作為預測,剩餘的部分來訓練模型,獲得其預測的輸出作為第i部分的新特徵。
  5. 對於測試集,直接用這k個模型的預測值均值作為新的特徵。
  6. 這樣k次下來,整個數據集都獲得了這個模型構建的New Feature。n個模型訓練下來,這個模型就有n個New Features。
  7. 把New Features和label作為新的分類器的輸入進行訓練。然後輸入測試集的New Features輸入模型獲得最終的預測結果。

8 Blending

Blending直接用不相交的數據集用於不同層的訓練。

以兩層的Blending為例,訓練集劃分為兩部分(d1,d2),測試集為test。

  1. 第一層:用d1訓練多個模型,講其對d2和test的預測結果作為第二層的New Features。
  2. 第二層:用d2的New Features和標籤訓練新的分類器,然後把test的New Features輸入作為最終的預測值。

融合的條件

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

Python實現

(1)Stacking

'''5折stacking'''n_folds = 5skf = list(StratifiedKFold(y, n_folds))for j, clf in enumerate(clfs): '''依次訓練各個單模型''' dataset_blend_test_j = np.zeros((X_predict.shape[0], len(skf))) for i, (train, test) in enumerate(skf): '''使用第i個部分作為預測,剩餘的部分來訓練模型,獲得其預測的輸出作為第i部分的新特徵。''' X_train, y_train, X_test, y_test = X[train], y[train], X[test], y[test] clf.fit(X_train, y_train) y_submission = clf.predict_proba(X_test)[:, 1] dataset_blend_train[test, j] = y_submission dataset_blend_test_j[:, i] = clf.predict_proba(X_predict)[:, 1] '''對於測試集,直接用這k個模型的預測值均值作為新的特徵。''' dataset_blend_test[:, j] = dataset_blend_test_j.mean(1)'''融合使用的模型'''clf = GradientBoostingClassifier(learning_rate=0.02, subsample=0.5, max_depth=6, n_estimators=30)clf.fit(dataset_blend_train, y)y_submission = clf.predict_proba(dataset_blend_test)[:, 1]

(2)Blending

一個兩層的Blending的實現

'''切分訓練數據集為d1,d2兩部分'''X_d1, X_d2, y_d1, y_d2 = train_test_split(X, y, test_size=0.5, random_state=2017)dataset_blend_train = np.zeros((X_d2.shape[0], len(clfs)))dataset_blend_test = np.zeros((X_predict.shape[0], len(clfs)))for j, clf in enumerate(clfs): '''依次訓練各個單模型''' # print(j, clf) '''使用第1個部分作為預測,第2部分來訓練模型,獲得其預測的輸出作為第2部分的新特徵。''' # X_train, y_train, X_test, y_test = X[train], y[train], X[test], y[test] clf.fit(X_train, y_train) y_submission = clf.predict_proba(X_test)[:, 1] dataset_blend_train[:, j] = y_submission '''對於測試集,直接用這k個模型的預測值作為新的特徵。''' dataset_blend_test[:, j] = clf.predict_proba(X_predict)[:, 1] print("val auc Score: %f" % roc_auc_score(y_predict, dataset_blend_test[:, j]))'''融合使用的模型'''# clf = LogisticRegression()clf = GradientBoostingClassifier(learning_rate=0.02, subsample=0.5, max_depth=6, n_estimators=30)clf.fit(dataset_blend_train, y_test)y_submission = clf.predict_proba(dataset_blend_test)[:, 1] 

Reference

  1. HUMAN ENSEMBLE LEARNING
  2. https://mlwave.com/kaggle-ensembling-guide/
  3. https://dnc1994.com/2016/04/rank-10-percent-in-first-kaggle-competition/
  4. https://zhuanlan.zhihu.com/p/25836678


分享到:


相關文章: