1. 程式人生 > >金融貸款逾期的模型構建7——模型融合

金融貸款逾期的模型構建7——模型融合

文章目錄


資料傳送門(data.csv)https://pan.baidu.com/s/1G1b2QJjYkkk7LDfGorbj5Q
目標:資料集是金融資料(非脫敏),要預測貸款使用者是否會逾期。表格中 “status” 是結果標籤:0表示未逾期,1表示逾期。

任務:用你目前評分最高的模型作為基準模型,和其他模型進行stacking融合,得到最終模型及評分果。

一、整合學習

整合學習是將幾種機器學習演算法組合成一個預測模型的演算法,以達到減小方差(bagging)、偏差(boosting)或改進預測(stacking)

的效果。

1、Bagging

基本思想:給定大小為 n n 的訓練集 D D ,Bagging 從中均勻、有放回地選出 m

m 個大小為 n n' 的子集 D i D_i ,作為新的訓練集。在這麼 m m 個訓練集上使用分類、迴歸等演算法,可以得到 m m 個模型,再通過平均值(常用於迴歸問題)、投票法(常用於分類問題)等方法綜合產生預測結果,即可得到 Bagging 模型。
在這裡插入圖片描述

優點:高效、可並行實現、能不經修改的適用於多分類和迴歸任務、包外估計。

典型模型:隨機森林(Random Forest)

2、Boosting

基本思想:個體學習器之間存在強依賴關係,必須序列序列化生成的整合學習方法。對訓練樣本分佈調整,主要是通過增加誤分類樣本的權重,降低正確分類樣本的權重。

工作機制如下:

  • 先從初始訓練集中學習一個基學習器;
  • 根據基學習器的表現對訓練樣本分佈進行調整,使得先前基學習器做錯的訓練樣本在後續收到更多關注;
  • 基於調整後的樣本分佈來訓練下一個基學習器;
  • 如此反覆,直到基學習器數目達到 T,最終將這 T 個基學習器進行加權結合。
    在這裡插入圖片描述
    典型模型:Adaboost

3、Stacking

概述:將個體機器學習器的結果結合在一起,即對學習器的結果再加上一層學習器。將訓練集學習器的學習結果作為輸入,將訓練集的輸出作為輸出,重新訓練一個學習器來得到最終結果。(也就是常說的兩層)

術語

  • 弱學習器稱為初級學習器,將用於結合的學習器稱為次級學習器;
  • 對於測試集,我們首先用初級學習器預測一次,得到次級學習器的輸入樣本,再用次級學習器預測一次,得到最終的預測結果。

(1)核心圖解

在這裡插入圖片描述
對於每一輪的 5-fold,Model 1都要做滿5次的訓練和預測。

a、構建新的訓練集

  1. 先將訓練集 D T r a i n i n g D a t a D(Training Data) 拆成 k k 個大小相似但互不相交的子集 D 1 , D 2 , , D k D_1,D_2,…,D_k
  2. D j = D D j D_j'= D - D_j ,在 D j D_j' 上訓練一個弱學習器 L j L_j 。將 D j D_j 作為測試集,獲得 L j L_j D j D_j 上的輸出 D j D_j''
  3. 步驟2可以得到 k k 個弱學習器以及 k k 個相應的輸出 D j D_j'' ,這個 k k 個輸出加上原本的類標構成新的訓練集 D n D_n
  4. D n D_n 訓練次學習器 L L L L 即為最後的學習器。

b、構建新的測試集

  1. 對於每個訓練好的一個弱學習器 L j L_j ,在測試集(Test Data,圖中所示綠色部分,不要與上面的“測試集”混淆。注意:此處是測試集的全部)進行預測,將 k k 次的預測結果取平均作為新的預測集。

c、最終的訓練與預測

  1. 訓練集為構建新的訓練集步驟得到的訓練集,測試集為構建新的測試集得到的測試集
  2. 訓練分類器並預測。

(2)示例

a、構建新的訓練集

Train Data有890行。(請對應圖中的上層部分)

每1次的fold,都會生成 713行 小train, 178行 小test。我們用Model 1來訓練 713行的小train,然後預測 178行 小test。預測的結果是長度為 178 的預測值。

這樣的動作走5次! 長度為178 的預測值 X 5 = 890 預測值,剛好和Train data長度吻合。這個890預測值是Model 1產生的,我們先存著,因為,一會讓它將是第二層模型的訓練來源。

重點:這一步產生的預測值我們可以轉成 890 X 1 (890 行,1列),記作 P1 (大寫P)

b、構建新的測試集

Test Data 有 418 行。(請對應圖中的下層部分,對對對,綠綠的那些框框)

每1次的fold,713行 小train訓練出來的Model 1要去預測我們全部的Test Data(全部!因為Test Data沒有加入5-fold,所以每次都是全部!)。此時,Model 1的預測結果是長度為418的預測值。

這樣的動作走5次!我們可以得到一個 5 X 418 的預測值矩陣。然後我們根據行來就平均值,最後得到一個 1 X 418 的平均預測值。

重點:這一步產生的預測值我們可以轉成 418 X 1 (418行,1列),記作 p1 (小寫p)

c、多模型的處理

走到這裡,你的第一層的Model 1完成了它的使命。

第一層還會有其他Model的,比如Model 2,同樣的走一遍, 我們有可以得到 890 X 1 (P2) 和 418 X 1 (p2) 列預測值。

這樣吧,假設你第一層有3個模型,這樣你就會得到:

來自5-fold的預測值矩陣 890 X 3,(P1,P2, P3) 和 來自Test Data預測值矩陣 418 X 3, (p1, p2, p3)。

d、最終的訓練與預測

來自5-fold的預測值矩陣 890 X 3 作為你的Train Data,訓練第二層的模型
來自Test Data預測值矩陣 418 X 3 就是你的Test Data,用訓練好的模型來預測他們吧。

三、實現

目前單模型評分最高的模型是 XGBoost,其評分如下:

準確率:  	訓練集:  0.8458 	測試集:  0.7898

1、手動實現

## 手動實現,stacking方法
def get_oof(clf, X_train, y_train, X_test):
    oof_train = np.zeros((ntrain,))     # 1 * 3327
    oof_test = np.zeros((ntest,))       # 1 * 1427
    oof_test_skf = np.empty((5, ntest)) # 5 * 1427

    # for clf in clfs:
    for i,(train_index, test_index) in enumerate(kf.split(X_train)): # X_train:3327*33
        print(train_index)
        kf_X_train = X_train.iloc[train_index]    # 2661*33
        kf_y_train = y_train.iloc[train_index]    # 2661*33
        kf_X_test = X_train.iloc[test_index]       # 666*7

        clf.fit(kf_X_train, kf_y_train)    # 學習分類器

        oof_train[test_index] = clf.predict(kf_X_test)  # 1*666
        oof_test_skf[i, :] = clf.predict(X_test)        # 測試集的預測作為測試資料

    oof_test[:] = oof_test_skf.mean(axis=0)   # 測試集的均值作為stcking的測試集
    return oof_train.reshape(-1, 1), oof_test.reshape(-1, 1)

## 使用多模型實現
rf_model = RandomForestClassifier()
xgbt_model = xgb.XGBClassifier()
gdbt_model = GradientBoostingClassifier()
dt_model = DecisionTreeClassifier()

train_sets = []
test_sets = []

for clf in [rf_model, xgbt_model, gdbt_model]:
    train_set, test_set = get_oof(clf, X_train, y_train, X_test)
    train_sets.append(train_set)
    test_sets.append(test_set)

meta_train = np.concatenate([result_set for result_set in train_sets], axis=1)
meta_test = np.concatenate([y_test_set for y_test_set in test_sets], axis=1)

# 使用決策樹作為次級分類器
dt_model = DecisionTreeClassifier()
dt_model.fit(meta_train,y_train)
# df_predict = dt_model.predict(meta_test)

## 模型評估
model_metrics(dt_model, meta_train, meta_test, y_train, y_test)

==》

<準確率>:
訓練集: 0.8031
測試集: 0.7884
<auc值>:
訓練集: 0.6853
測試集: 0.6579

2、StackingClassifier類實現

## 使用多模型實現
from mlxtend.classifier import StackingClassifier

rf_model = RandomForestClassifier()
xgbt_model = xgb.XGBClassifier()
gdbt_model = GradientBoostingClassifier()
dt_model = DecisionTreeClassifier()

sclf = StackingClassifier(classifiers=[rf_model,xgbt_model,gdbt_model],meta_classifier=dt_model)
sclf.fit(X_train,y_train)

for clf,label in zip([rf_model,xgbt_model,gdbt_model,sclf],['隨機森林','XGBoost','GBDT','StackingClassifier']):
    scores = cross_val_score(clf,X_train,y_train,cv = 5,scoring='accuracy')
    print("Accuracy: %0.2f (+/- %0.2f) [%s]"% (scores.mean(), scores.std(), label))

==》

Accuracy: 0.77 (+/- 0.01) [隨機森林]
Accuracy: 0.80 (+/- 0.00) [XGBoost]
Accuracy: 0.79 (+/- 0.01) [GBDT]
Accuracy: 0.78 (+/- 0.01) [StackingClassifier]

小結

  • 從結果來看,本文的Stacking結果和只是用XGBoost的結果基本持平(實際略低於XGBoost)。
    • 換用一些弱分類器作為基本分類器效果會怎麼樣?

Reference

  1. https://zhuanlan.zhihu.com/p/26890738