金融貸款逾期的模型構建7——模型融合
文章目錄
資料傳送門(data.csv): https://pan.baidu.com/s/1G1b2QJjYkkk7LDfGorbj5Q
目標:資料集是金融資料(非脫敏),要預測貸款使用者是否會逾期。表格中 “status” 是結果標籤:0表示未逾期,1表示逾期。
任務:用你目前評分最高的模型作為基準模型,和其他模型進行stacking融合,得到最終模型及評分果。
一、整合學習
整合學習是將幾種機器學習演算法組合成一個預測模型的演算法,以達到減小方差(bagging)、偏差(boosting)或改進預測(stacking)
1、Bagging
基本思想:給定大小為
的訓練集
,Bagging 從中均勻、有放回地選出
個大小為
的子集
,作為新的訓練集。在這麼
個訓練集上使用分類、迴歸等演算法,可以得到
個模型,再通過平均值(常用於迴歸問題)、投票法(常用於分類問題)等方法綜合產生預測結果,即可得到 Bagging 模型。
優點:高效、可並行實現、能不經修改的適用於多分類和迴歸任務、包外估計。
典型模型:隨機森林(Random Forest)
2、Boosting
基本思想:個體學習器之間存在強依賴關係,必須序列序列化生成的整合學習方法。對訓練樣本分佈調整,主要是通過增加誤分類樣本的權重,降低正確分類樣本的權重。
工作機制如下:
- 先從初始訓練集中學習一個基學習器;
- 根據基學習器的表現對訓練樣本分佈進行調整,使得先前基學習器做錯的訓練樣本在後續收到更多關注;
- 基於調整後的樣本分佈來訓練下一個基學習器;
- 如此反覆,直到基學習器數目達到 T,最終將這 T 個基學習器進行加權結合。
典型模型:Adaboost
3、Stacking
概述:將個體機器學習器的結果結合在一起,即對學習器的結果再加上一層學習器。將訓練集學習器的學習結果作為輸入,將訓練集的輸出作為輸出,重新訓練一個學習器來得到最終結果。(也就是常說的兩層)
術語:
- 弱學習器稱為初級學習器,將用於結合的學習器稱為次級學習器;
- 對於測試集,我們首先用初級學習器預測一次,得到次級學習器的輸入樣本,再用次級學習器預測一次,得到最終的預測結果。
(1)核心圖解
對於每一輪的 5-fold,Model 1都要做滿5次的訓練和預測。
a、構建新的訓練集
- 先將訓練集 拆成 個大小相似但互不相交的子集 ;
- 令 ,在 上訓練一個弱學習器 。將 作為測試集,獲得 在 上的輸出 ;
- 步驟2可以得到 個弱學習器以及 個相應的輸出 ,這個 個輸出加上原本的類標構成新的訓練集 ;
- 在 訓練次學習器 , 即為最後的學習器。
b、構建新的測試集
- 對於每個訓練好的一個弱學習器 ,在測試集(Test Data,圖中所示綠色部分,不要與上面的“測試集”混淆。注意:此處是測試集的全部)進行預測,將 次的預測結果取平均作為新的預測集。
c、最終的訓練與預測
- 訓練集為構建新的訓練集步驟得到的訓練集,測試集為構建新的測試集得到的測試集
- 訓練分類器並預測。
(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)。
- 換用一些弱分類器作為基本分類器效果會怎麼樣?