【机器学习-贷款用户逾期情况分析2】3.stacking模型融合
3.0 任務說明
用你目前評分最高的模型作為基準模型,和其他模型進行stacking融合,得到最終模型及評分果。
?
3.1 stacking模型融合
Stacking(有時候也稱之為stacked generalization)是指訓練一個模型用于組合(combine)其他各個模型。即首先我們先訓練多個不同的模型,然后再以之前訓練的各個模型的輸出為輸入來訓練一個模型,以得到一個最終的輸出。如果可以選用任意一個組合算法,那么理論上,Stacking可以表示上面提到的各種Ensemble方法。然而,實際中,我們通常使用單層logistic回歸作為組合模型。
對于stacking的過程這篇文章我認為講得比較清楚:
https://blog.csdn.net/qq_32742009/article/details/81366768
我這里再簡要說明一下。首先說明一下,stacking可以看成兩層結構,第一層結構的輸出作為第二層的輸入。
我們第一層以svm,lightgbm,xgboost為例,第二層以LR為例作一個講解,假設訓練集有15000個數據,測試集3000個數據,步驟如下:
(1)用svm作五折交叉訓練,訓練五次,每次將訓練集劃分為5份,其中一份作為驗證集。
(2)每一次將驗證集的預測值豎著組合在一起,5次的預測值分別為a1,a2,a3,a4,a5,假設a的大小都是3000*1,將這5個a值再豎著拼在一起,組成A1,A1的大小為15000*1。A1為上圖中最后一個橙塊。此時A1各個特征對應的標簽設為Label_new。
(3)將每一次驗證集得到的結果對Test Data作測試,假設每一次測試后產生2000*1的數據,那么五次驗證后產生,5個2000*1的數據b1,b2,b3,b4,b5。b1,b2,b3,b4,b5各個位置相加后取平均值得到1個2000*1的數據B1。這個B1為上圖中倒數第二個綠塊。
(3)同理,將gbm和xgb五折交叉訓練后的預測值豎著組成在一起,分別組成A2,A3。將他們對Test Data作預測,得到B2,B3。
(4)將A1,A2,A3橫著合并得到一個15000行3列的矩陣A,將B1,B2,B3橫著合并得到一個2000行3列的矩陣B。
(5)矩陣A即為新的訓練集的特征,矩陣B即為新的測試集的特征。讓下一層的模型,基于他們進一步訓練。矩陣A的標簽是上面步驟2個Label_new,矩陣B的標簽即為原來測試集的標簽。
我自己寫的函數如下:
def Stacking(model,num_folds,x_train,y_train,x_test,y_test): #輸入的模型集合里最后一個模型用作stacking里第二層模型y_train=np.array(y_train)x_train_folds = []y_train_folds = []x_train_folds=np.array_split(x_train,num_folds)y_train_folds=np.array_split(y_train,num_folds)y_pred_A=[]y_pred_testseting_A=[]label_1=[]model_len=len(model)for i in range (0,model_len-1):y_pred_A.append([])y_pred_testseting_A.append([])for i in range (num_folds): #五折交叉驗證x_train_now=np.zeros((1,x_train.shape[1]))y_train_now=np.array([[0]])for k in range (5): #這里的循環是為了將驗證集組合在一塊兒if(k!=i):x_train_now=np.vstack((x_train_now,x_train_folds[k]))y_train_folds[k]=y_train_folds[k].reshape(y_train_folds[k].shape[0],1)y_train_now=np.vstack((y_train_now,y_train_folds[k]))x_validation=x_train_folds[i]y_validation=y_train_folds[i]y_validation=y_validation.reshape((y_validation.shape[0],1))x_train_now=np.delete(x_train_now,0,0) #由于之前vstack之前有1列0,現在需要刪除。y_train_now=np.delete(y_train_now,0,0) for model_nums in range(0,model_len-1):model[model_nums].fit(x_train_now,y_train_now)label_1.append(y_validation)for j in range(0,model_len-1):y_pred_A[j].append ( model[j].predict(x_validation))y_pred_testseting_A[j].append(model[j].predict(x_test))y_pred_A[j][i]=y_pred_A[j][i].reshape((y_pred_A[j][i].shape[0],1))y_pred_testseting_A[j][i]=y_pred_testseting_A[j][i].reshape((y_pred_testseting_A[j][i].shape[0],1))A=[] # A里面裝博客里寫的A1,A2,A3矩陣B=[] #B里面裝博客里寫的B1,B2..矩陣for i in range(0,model_len-1):A.append([])B.append([])for j in range(0,model_len-1):y_preds=np.array([[0]])for i in range(num_folds):y_preds=np.vstack((y_preds,y_pred_A[j][i]))#將5次預測出來的標簽組在一起。y_preds=np.delete(y_preds,0,0)A[j].append(y_preds.copy())B1=np.zeros((x_test.shape[0],1))for i in range(num_folds):B1=B1+y_pred_testseting_A[j][i]B[j].append(B1/num_folds)x_train_new=np.zeros((A[0][0].shape[0],1))x_test_new=np.zeros((B[0][0].shape[0],1))label_layer1=np.array([[0]])for i in range(0,model_len-1):A_now=np.array(A[i]).reshape((A[0][0].shape[0],1))B_now=np.array(B[i]).reshape((B[0][0].shape[0],1))x_train_new=np.hstack((x_train_new,A_now))x_test_new=np.hstack((x_test_new,B_now))x_train_new=np.delete(x_train_new,0,1)x_test_new=np.delete(x_test_new,0,1) #第二層的訓練集和測試集特征for i in range(num_folds): print(label_1[i].shape)label_layer1=np.vstack((label_layer1,label_1[i])) #第二層訓練集標簽label_layer1=np.delete(label_layer1,0,0)y_train_new=label_layer1.copy()y_test_new=y_test.copy()y_test_new=np.array(y_test_new)y_test_new=y_test_new.reshape((y_test_new.shape[0]))model[model_len-1].fit(x_train_new,y_train_new)r,recall,precision,F1,auc=evaluate(model[model_len-1],x_test_new,y_test_new)print(r,recall,precision,F1,auc)我將邏輯回歸、lightgbm,rfc,gbdt作為第一層,xgboost作為第二層,代碼和結果如下:
Xgb = xgb.XGBClassifier() gbdt=GradientBoostingClassifier() gbm = lgb.LGBMClassifier() rfc = RandomForestClassifier() Dtree = tree.DecisionTreeClassifier() svm = SVC(probability=True) lr = LogisticRegressionCV() models=[] models.append(rfc);models.append(gbdt);models.append(gbm);models.append(lr);models.append(Xgb) Stacking(models,5,x_train,y_train,x_test,y_test)3.1 stacking接口
自己寫完函數才發現,在mlxtend包里有stacking接口,安裝直接pip即可:
pip install mlxtend。StackingClassifier 使用API及參數解析:
StackingClassifier(classifiers, meta_classifier, use_probas=False, average_probas=False, verbose=0, use_features_in_secondary=False)
參數:
classifiers : 基分類器,數組形式,[cl1, cl2, cl3]. 每個基分類器的屬性被存儲在類屬性 self.clfs_.
meta_classifier : 目標分類器,即將前面分類器合起來的分類器
use_probas : bool (default: False) ,如果設置為True, 那么目標分類器的輸入就是前面分類輸出的類別概率值而不是類別標簽
average_probas : bool (default: False),用來設置上一個參數當使用概率值輸出的時候是否使用平均值。
verbose : int, optional (default=0)。用來控制使用過程中的日志輸出,當 verbose = 0時,什么也不輸出, verbose = 1,輸出回歸器的序號和名字。verbose = 2,輸出詳細的參數信息。verbose > 2, 自動將verbose設置為小于2的,verbose -2.
use_features_in_secondary : bool (default: False). 如果設置為True,那么最終的目標分類器就被基分類器產生的數據和最初的數據集同時訓練。如果設置為False,最終的分類器只會使用基分類器產生的數據訓練。
屬性:
clfs_ : 每個基分類器的屬性,list, shape 為 [n_classifiers]。
meta_clf_ : 最終目標分類器的屬性
方法:
fit(X, y)
fit_transform(X, y=None, fit_params)
get_params(deep=True),如果是使用sklearn的GridSearch方法,那么返回分類器的各項參數。
predict(X)
predict_proba(X)
score(X, y, sample_weight=None), 對于給定數據集和給定label,返回評價accuracy
set_params(params),設置分類器的參數,params的設置方法和sklearn的格式一樣
代碼如下:
from mlxtend.classifier import StackingClassifiersclf = StackingClassifier(classifiers=[rfc, gbdt, gbm,lr], use_probas=True,average_probas=False,meta_classifier=Xgb) re = sclf.fit(x_train, y_train) evaluate(re,x_test,y_test)結果:
將stacking模型和其他模型寫一起對比,代碼如下(預處理見前兩篇文章):
import csv import os import numpy as np import random import requests import pandas as pd import matplotlib.pyplot as plt import sklearn from sklearn.linear_model import LogisticRegressionCV,LinearRegression from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn import metrics from sklearn.svm import SVC from sklearn import tree from sklearn.ensemble import RandomForestClassifier from sklearn.ensemble import GradientBoostingClassifier import xgboost as xgb from xgboost import plot_importance import lightgbm as lgb from mlxtend.classifier import StackingClassifierdef evaluate(re,x_test,y_test): #單個模型評估r = re.score(x_test,y_test)y_pred = re.predict(x_test) #測試數據預測值cmat=metrics.confusion_matrix(y_test, y_pred) #混淆矩陣y_scores=re.predict_proba(x_test) #預測出來的得分,有兩列,第一列為此值為0的概率,第二列為此值為1的概率y_scores=y_scores[:,1] #我們這里只需要預測為1的概率recall=metrics.recall_score(y_test, y_pred) #查全率precision=metrics.precision_score(y_test,y_pred) #查準率F1=metrics.f1_score(y_test,y_pred)auc=metrics.roc_auc_score(y_test, y_scores) #auc值return r,recall,precision,F1,aucdef evaluateAll(models,x_test,y_test): #所有模型評估length=len(models) #模型個數r=np.zeros((length));recall=np.zeros((length));precision=np.zeros((length));F1=np.zeros((length));auc=np.zeros((length))evaluates=np.zeros((length,5)) #裝所有的指標for i in range(length):r[i],recall[i],precision[i],F1[i],auc[i]=evaluate(models[i],x_test,y_test)evaluates[i][0]=r[i];evaluates[i][1]=recall[i];evaluates[i][2]=precision[i];evaluates[i][3]=F1[i];evaluates[i][4]=auc[i];return r,recall,precision,F1,auc,evaluatesdef drawROC(re,x_test,y_test,title): #單個模型畫ROCy_scores=re.predict_proba(x_test) #預測出來的得分,有兩列,第一列為此值為0的概率,第二列為此值為1的概率y_scores=y_scores[:,1] #我們這里只需要預測為1的概率fpr, tpr, thresholds=metrics.roc_curve(y_test,y_scores,pos_label=None,sample_weight=None,drop_intermediate=True)auc=metrics.auc(fpr,tpr)plt.plot(fpr,tpr,marker = 'o',label='AUC:{a:0.2f}'.format(a=auc))plt.legend(loc="lower right")plt.xlabel('False Positive Rate')plt.ylabel('True Positive Rate')plt.title(title)plt.show()def drawAllROC(models,models_name,x_test,y_test,title): #畫所有的ROC曲線nums=len(models) #模型個數y_scores0=[] y_scores=[]for i in range(nums):y_scores0.append(models[i].predict_proba(x_test)) #預測出來的得分,有兩列,第一列為此值為0的概率,第二列為此值為1的概率 y_scores.append(y_scores0[i][:,1]) #我們這里只需要預測為1的概率fpr0, tpr0, thresholds0=metrics.roc_curve(y_test,y_scores[0],pos_label=None,sample_weight=None,drop_intermediate=True)fpr=[]tpr=[]thresholds=[]auc=[]plt.figure()plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')for i in range(nums):fpr.append((metrics.roc_curve(y_test,y_scores[i],pos_label=None,sample_weight=None,drop_intermediate=True))[0])tpr.append((metrics.roc_curve(y_test,y_scores[i],pos_label=None,sample_weight=None,drop_intermediate=True))[1])thresholds.append((metrics.roc_curve(y_test,y_scores[i],pos_label=None,sample_weight=None,drop_intermediate=True))[2])auc.append(metrics.auc(fpr[i],tpr[i]))plt.plot(fpr[i],tpr[i],label='{0} (AUC:{1:0.2f})'.format(models_name[i], auc[i]))plt.legend(loc="lower right")plt.xlabel('False Positive Rate')plt.ylabel('True Positive Rate')plt.title(title)plt.show() #-------------------------------------劃分數據----------------------------------------#x_train, x_test,y_train,y_test= train_test_split(X, y, test_size=0.3,random_state=2018) #數據集三七分,隨機種子2018 #-------------------------------------數據標準化----------------------------------------# ss = StandardScaler() x_train = ss.fit_transform(x_train) #數據標準化 x_test = ss.fit_transform(x_test) #數據標準化#-------------------------------------logstic----------------------------------------# lr = LogisticRegressionCV() lr.fit(x_train,y_train) #-------------------------------------svm-----------------------------------------# svm = SVC(probability=True) svm.fit(x_train,y_train) #-------------------------------------tree-----------------------------------------#Dtree = tree.DecisionTreeClassifier()Dtree.fit(x_train, y_train) #-------------------------------------隨機森林-----------------------------------------#rfc = RandomForestClassifier() rfc.fit(x_train, y_train)#-------------------------------------gbdt-----------------------------------------# gbdt=GradientBoostingClassifier() gbdt.fit(x_train, y_train)#-------------------------------------XGBoost-----------------------------------------#Xgb = xgb.XGBClassifier() Xgb.fit(x_train, y_train) #-------------------------------------lightgbm-----------------------------------------# gbm = lgb.LGBMClassifier() gbm.fit(x_train, y_train)#-------------------------------------Stacking-----------------------------------------#sclf = StackingClassifier(classifiers=[rfc, gbdt, gbm,lr], use_probas=True,average_probas=False,meta_classifier=Xgb) sclf.fit(x_train, y_train)#---------------------------模型評估-----------------------------# models=[] models.append(lr);models.append(svm);models.append(Dtree);models.append(rfc);models.append(gbdt);models.append(Xgb);models.append(gbm);models.append(sclf) models_name=['LR','SVM','TREE','RFC','GBDT','XGBoost','LightGBM','sclf']r,recall,precision,F1,auc,evaluates=evaluateAll(models,x_test,y_test) for i in range(len(models)):print(models_name[i],evaluates[i]) drawAllROC(models,models_name,x_test,y_test,"all")結果:
總結
以上是生活随笔為你收集整理的【机器学习-贷款用户逾期情况分析2】3.stacking模型融合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CentOS 7阿里云服务器IP地址和M
- 下一篇: 搜狗百科创建词条的技巧和方法有哪些?