欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

集成学习Stacking(模型融合)

程序员文章站 2022-07-14 14:51:07
...

集成学习Stacking(模型融合)

简介

​ 在数据竞赛中有这一种方法,它是一个强有力的武器,只要能够善于使用,它就是无往不利,无坚不摧的那把利剑,更是被称为数据竞赛胜出的杀手锏。它通过构建并结合多个弱学习器组合形成一个强大的学习器来完成学习任务,俗称为模型融合,其实他采用的就是集成学习的思路。

​ 接下来就先介绍模型融合(集成学习)中的其中一个方法stack。

基本思路

1、划分数据集

​ 我们将数据集(data)划分为训练集(train)和测试集(test)两部分,然后使用k折交叉切分,将总训练集划分为5等份,4份作为小训练集(train_train),1份作为验证集(train_val)。

​ 划分5次,直到每一等份都做过验证集为止,这样就有5种不同的小训练集和验证集了。

集成学习Stacking(模型融合)

2、生成存储数组

在生成模型之前,我们需要先生成两个数组,一个用来存放最终的训练集生成向量的dataset_train,一个用于存放最终的训测试集向量的dataset_test。

  • dataset_train是一个模型作为一列,训练集train长度作为行数。

集成学习Stacking(模型融合)
集成学习Stacking(模型融合)

  • dataset_test也为一个模型作为一列,训练集test长度作为行数。

集成学习Stacking(模型融合)
集成学习Stacking(模型融合)

3、训练模型

开始生成模型,根据自己的需求选择算法,我使用了基于随机决策树的平均算法RandomForest算法和Extra-Trees算法(其中可分为gini,entropy),还有GBDT来生成模型。

以RandomForest为例,先将第一种小训练集作为输入喂给RandomForestClassifier(gini),生成模型model_1,再将第一种验证集(train_val)的特征喂给model_1得到输出向量。

训练集切分了5层,验证集只占其一,所以这时候验证集的预测结果就是训练集的五分之一,我们用剩下的4种小训练集分别作为输入得到4个模型,再一一匹配各自的验证集,获得4份验证集输出向量,将其相加,就得到一份完整的训练集输出向量。然后将其存入dataset_train数组中对应的模型列中,作为下一步的输入。

在得到5种小训练集模型的同时,我们将测试集的特征也一一喂给这5个模型,得到5种测试集输出向量,将他们取平均合为一个结果,存入dataset_test数组中对应的模型列中,作为下一步的测试集。

集成学习Stacking(模型融合)

RandomForest模型训练完以后,我们就可以用auc验证一下这个模型准确率了。

集成学习Stacking(模型融合)

由于我们使用了五种算法,所以需要将以上步骤重复五次生成5个不同的模型即可。

集成学习Stacking(模型融合)

4、模型融合

在这个阶段我们根据自己需求选择算法,我这里选择了GBDT(一开始选择LR,但是效果不大好,所以这玩意见仁见智)。

在训练模型阶段,我们得到了数组dataset_train和dataset_test,如下图。

  • dataset_train每一列对应每一个算法模型,例如第一列就为五个小训练集的RandomForestClassifier(gini)模型对五个验证集的预测结果相加。

集成学习Stacking(模型融合)

  • 而dataset_test则是五个小训练集的RandomForestClassifier(gini)模型对测试集test的预测结果取平均。

集成学习Stacking(模型融合)

用dataset_train作为输入与和原始训练集标签fit成model。

然后对dataset_test喂给model,生成输出向量,对其进行归一化。

用auc进行评估。

集成学习Stacking(模型融合)

喜闻乐见的代码环节

这是自己实现的一个简单的代码,可以用于理清入门思路

from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier,ExtraTreesClassifier,GradientBoostingClassifier
from sklearn.model_selection import train_test_split,StratifiedKFold
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_blobs

data,label=make_blobs(n_samples = 10000,centers = 2,random_state = 0,cluster_std = 0.60)
#划分训练集和测试
x_train,x_test,y_train,y_test=train_test_split(data,label,test_size=0.33,random_state=0)

clfs = [RandomForestClassifier(n_estimators = 100,n_jobs=-1,criterion = 'gini'),
        RandomForestClassifier(n_estimators = 100,n_jobs=-1,criterion = 'entropy'),
        ExtraTreesClassifier(n_estimators = 100,n_jobs = -1,criterion = 'gini'),
        ExtraTreesClassifier(n_estimators = 100,n_jobs=-1,criterion = 'entropy'),
        GradientBoostingClassifier(learning_rate = 0.05,subsample = 0.5,max_depth = 6,n_estimators=5)
]

#将训练集分层采样5折交叉切分,四层训练集,一层验证集
skf= list(StratifiedKFold(n_splits = 5,random_state = 0,shuffle = False).split(x_train, y_train))

#多维数组,用来存放每个模型生成的训练集预测向量
dataset_train = np.zeros((x_train.shape[0],len(clfs)))
#多维数组,用来存放每个模型生成的测试集预测向量
dataset_test = np.zeros((x_test.shape[0],len(clfs)))

for j,clf in enumerate(clfs):
#    print (j,clf)
    dataset_test_j = np.zeros((x_test.shape[0],len(skf)))
    for i,(train,val) in enumerate(skf):
        #使用第i个部分作为预测,剩余的部分来训练模型,获得其预测的输出作为第i部分的新特征。
#        print('fold',i)
        #从训练集中选出小训练集和验证集
        x_train_train,y_train_train= x_train[train],y_train[train]
        x_train_val,y_train_val = x_train[val],y_train[val]
        #用五种不一样小训练集获得五个小模型
        clf.fit(x_train_train,y_train_train)
        #每一个小模型得出验证集的预测结果,也就是得出全部训练集的1/5
        #在五次小模型循环预测完后就得到全部训练集的预测值
        dataset_train[val,j] = clf.predict_proba(x_train_val)[:,1] 
        #五个小模型将test全部训练一遍
        dataset_test_j[:,i] = clf.predict_proba(x_test)[:,1] 
    #取五次test训练结果的平均
    dataset_test[:,j] = dataset_test_j.mean(1)
    print("val auc Score: %f" % roc_auc_score(y_test, dataset_test[:, j]))
    
#模型融合
clf=GradientBoostingClassifier(learning_rate=0.2,subsample=0.5,max_depth=6,n_estimators=30)
clf.fit(dataset_train,y_train)#此时dataset_train是训练集的预测值
#生成预测集结果向量
y_submission = clf.predict_proba(dataset_test)[:,1]
y_submission = (y_submission - y_submission.min()) / (y_submission.max() - y_submission.min())
print('模型融合后auc')
print("val auc Score: %f" % (roc_auc_score(y_test, y_submission)))

欢迎关注我的微信公众号:

数据挖掘初学者
集成学习Stacking(模型融合)