1. 程式人生 > >ML - 貸款使用者逾期情況分析4 - 模型融合之Stacking

ML - 貸款使用者逾期情況分析4 - 模型融合之Stacking

文章目錄

模型融合之Stacking (判定貸款使用者是否逾期)

給定金融資料,預測貸款使用者是否會逾期。(status是標籤:0表示未逾期,1表示逾期。)

Task7(模型融合) - 對Task6調優後的模型, 進行模型融合。例如, 用目前評分最高的模型作為基準模型, 和其他模型進行stacking模型融合, 得到最終模型和評分。

1. 理論介紹

1.1 系統解釋

學習器的結合策略有:平均法、投票法和學習法。
對迴歸問題,平均法就是對若干個學習器的輸出進行平均得到最終的預測輸出。複雜點還可以對每個學習器設定權重。
對分類問題,投票法就是多數表決法(少數服從多數)。

Stacking學習法的代表方法,這裡我們不再對學習器的結果做簡單的邏輯處理,而是再加上一層學習器。將訓練集學習器的學習結果作為輸入,將訓練集的輸出作為輸出,重新訓練一個學習器來得到最終結果。

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

1.2 詳細解釋

stacking有一張經典的圖:
Stacking

下面用語言對其詳細解釋。

首先選幾個模型作為第一層模型進行5折交叉驗證。

例如:分別選用LR、SVM和決策樹作為第一層模型Model1,分別實施以下步驟:
1)把train分train1~train5,共5份,用其中4份預測剩下的那份,同時預測test資料,這樣的過程做5次,生成5份train(原train樣本數/5)資料和5份test資料。
2)把5份預測的train資料縱向疊起來(即為原來的整個train,只是順序不同),把test預測的結果做平均。

將三個模型得到的train並列合併成一個3列的矩陣作為training-data,得到的test並列合併成一個3列的矩陣作為testing-data。
讓下一層的模型,基於他們進一步訓練。

2. 程式碼

import pandas as pd
import pickle

# 資料集預覽
data = pd.read_csv('data.csv')
# 去重
data.drop_duplicates(inplace=True)
print(data.shape)
data.head()
# 載入特徵
with open('feature.pkl', 'rb') as f:
    X = pickle.load(f)

# 觀測正負樣本是否均衡
y = data.status
y.value_counts()
# 劃分訓練集測試集
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,random_state=2333)

# 特徵歸一化
std = StandardScaler()
X_train = std.fit_transform(X_train.values)
X_test = std.transform(X_test.values)

模型評估

from sklearn.metrics import accuracy_score, roc_auc_score

def model_metrics(clf, X_train, X_test, y_train, y_test):
    # 預測
    y_train_pred = clf.predict(X_train)
    y_test_pred = clf.predict(X_test)
    
    y_train_proba = clf.predict_proba(X_train)[:,1]
    y_test_proba = clf.predict_proba(X_test)[:,1]
    
    # 準確率
    print('[準確率]', end = ' ')
    print('訓練集:', '%.4f'%accuracy_score(y_train, y_train_pred), end = ' ')
    print('測試集:', '%.4f'%accuracy_score(y_test, y_test_pred))
    
    # auc取值:用roc_auc_score或auc
    print('[auc值]', end = ' ')
    print('訓練集:', '%.4f'%roc_auc_score(y_train, y_train_proba), end = ' ')
    print('測試集:', '%.4f'%roc_auc_score(y_test, y_test_proba))

模型選擇

from sklearn.linear_model import LogisticRegression
from sklearn import svm
from sklearn.tree import DecisionTreeClassifier
from xgboost.sklearn import XGBClassifier
from lightgbm.sklearn import LGBMClassifier

from mlxtend.classifier import StackingClassifier

# 模型調優後得到的引數
lr = LogisticRegression(C = 0.1, penalty = 'l1')
svm_linear = svm.SVC(C = 0.01, kernel = 'linear', probability=True)
svm_poly =  svm.SVC(C = 0.01, kernel = 'poly', probability=True)
svm_rbf =  svm.SVC(gamma = 0.01, C =0.01 , probability=True)
svm_sigmoid =  svm.SVC(C = 0.01, kernel = 'sigmoid',probability=True)
dt = DecisionTreeClassifier(max_depth=11,min_samples_split=550,min_samples_leaf=80,max_features=19)
xgb = XGBClassifier(learning_rate =0.01, n_estimators=180, max_depth=3, min_child_weight=5, 
                    gamma=0.4, subsample=0.5, colsample_bytree=0.9, reg_alpha=1, 
                    objective= 'binary:logistic', nthread=4,scale_pos_weight=1, seed=27)
lgb = LGBMClassifier(learning_rate =0.1, n_estimators=60, max_depth=3, min_child_weight=11, 
                    gamma=0.1, subsample=0.5, colsample_bytree=0.8, reg_alpha=1e-5, 
                    nthread=4,scale_pos_weight=1, seed=27)

2.1 調包實現

使用4種SVM、決策樹、XGBoost和LightGBM作為初級分類器,LR作為次級分類器。

1)將初級分類器產生的類別標籤作為新特徵

import warnings
warnings.filterwarnings("ignore")

sclf = StackingClassifier(classifiers=[svm_linear, svm_poly, svm_rbf, 
                                       svm_sigmoid, dt, xgb, lgb], meta_classifier=lr)
sclf.fit(X_train, y_train.values)
model_metrics(sclf, X_train, X_test, y_train, y_test)

輸出

[準確率] 訓練集: 0.8242 測試集: 0.8066
[auc值] 訓練集: 0.6981 測試集: 0.6765

2)將初級分類器產生的輸出類概率作為新特徵
對輸出概率use_probas=True,有兩種不同的處理方式。

假設有2個初級分類器和3個類別輸出概率:p1=[0.2,0.5,0.3],p2=[0.3,0.4,0.4]。
如果average_probas=True,則對分類器的結果求平均,得到:p=[0.25,0.45,0.35]
[推薦]如果average_probas=False,則分類器的所有結果都保留作為新的特徵:p=[0.2,0.5,0.3,0.3,0.4,0.4]

sclf = StackingClassifier(classifiers=[svm_linear, svm_poly, svm_rbf, svm_sigmoid, dt, xgb, lgb],  meta_classifier=lr, use_probas=True,average_probas=False)
sclf.fit(X_train, y_train.values)
model_metrics(sclf, X_train, X_test, y_train, y_test)

輸出

[準確率] 訓練集: 0.8365 測試集: 0.8017
[auc值] 訓練集: 0.8773 測試集: 0.7962

2.2 自己實現

參見部落格模型融合之blending和stacking

遇到的問題

1)sclf.fit(X,y)時會報錯
解決:注意X_train是array,而y_train是Series且索引不一定從0開始。此處我們取y_train.values,將y_train也轉成array。

Reference

詳解stacking過程
整合學習原理小結
整合學習stacking
【機器學習】模型融合方法概述

More

程式碼參見Github: https://github.com/libihan/Exercise-ML