模型融合之Stacking and Blending

模型融合的基本思想就是集成单个模型以提升整体性能,也就是所说的 Ensemble Model
常见的模型融合方法有:Bagging、Boosting、Stacking、Blending。

Bagging:该方法通常考虑的是同质弱学习器,相互独立地并行学习这些弱学习器,并按照某种确定性的平均过程将它们组合起来。单个学习器之间独立学习,学习器之间无依赖,因此可以高效并行学习。模型代表有 随机森林(Random Forest)

Boosting:该方法通常考虑的也是同质弱学习器。它以一种高度自适应的方法顺序地学习这些弱学习器(每个弱学习器都依赖于前面的学习器),并按照某种确定性的策略将它们组合起来。学习器之间相互依赖,只能在样本上并行,在学习器上无法并行。这类模型有:Adaboost、GBDT、XGBoost等。

Stacking:该方法通常考虑的是异质弱学习器,并行地学习它们,并通过训练一个「元模型」将它们组合起来,根据不同弱模型的预测结果输出一个最终的预测结果。

Blending:Blending与Stacking大致相同,主要区别在于训练集不是通过K-Fold的CV策略来获得预测值从而生成第二阶段模型的特征,而是建立一个Holdout集。简单来说,Blending直接用不相交的数据集用于不同层的训练。
以两层的Blending为例,训练集划分为两部分(d1,d2),测试集为test。
第一层:用d1训练多个模型,将其对d2和test的预测结果作为第二层的New Features。
第二层:用d2的New Features和标签训练新的分类器,然后把test的New Features输入作为最终的测试集,对test预测出的结果就是最终的模型融合的值。
缺点是,d1未参与第二层的模型训练,每一层的训练数据量较上一层都有所减少,后续的模型看到的训练数据越来越少。

下面结合模型架构和代码重点解释一下 Stacking和Blending方法。

Stacking

在这里插入图片描述

from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier, ExtraTreesClassifier, GradientBoostingClassifier
from sklearn.model_selection import train_test_split
from sklearn.model_selection import StratifiedKFold
import numpy as np
from sklearn.metrics import roc_auc_score
from sklearn.datasets.samples_generator import make_blobs
# 创建训练的数据集
data, target = make_blobs(n_samples=50000, centers=2, random_state=0, cluster_std=0.60)
# 模型融合中使用到的各个单模型
clfs = [RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
        RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'),
        ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
        ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'),
        GradientBoostingClassifier(learning_rate=0.05, subsample=0.5, max_depth=6, n_estimators=5)]
# 切分一部分数据作为测试集
X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.33, random_state=2017)
dataset_blend_train = np.zeros((X_train.shape[0], len(clfs)))
dataset_blend_test = np.zeros((X_test.shape[0], len(clfs)))

# 定义交叉验证折数
# 4折stacking
n_folds = 4

skf = StratifiedKFold(n_splits=n_folds)
train_val = list(skf.split(X_train, y_train))

# 第一层将原始X作为特征
for j, clf in enumerate(clfs):
    dataset_blend_test_j = np.zeros((X_test.shape[0], n_folds))
    for i, (train, val) in enumerate(train_val):
        # 使用第i个部分作为预测,剩余的部分来训练模型,获得其预测的输出作为第i部分的新特征。
        X_tra, y_tra, X_val, y_val = X_train[train], y_train[train], X_train[val], y_train[val]
        clf.fit(X_tra, y_tra)
        y_submission = clf.predict_proba(X_val)[:, 1]
        dataset_blend_train[val, j] = y_submission
        dataset_blend_test_j[:, i] = clf.predict_proba(X_test)[:, 1]
    # 对于测试集,直接用这k个模型的预测值均值作为新的特征。
    dataset_blend_test[:, j] = dataset_blend_test_j.mean(1)
    print("Model Name: {0:<30},  Val auc score: {1:.5f}".format(clf.__class__.__name__, roc_auc_score(y_test, dataset_blend_test[:, j])))

打印结果:
Model Name: RandomForestClassifier , Val auc score: 0.99956
Model Name: RandomForestClassifier , Val auc score: 0.99963
Model Name: ExtraTreesClassifier , Val auc score: 0.99980
Model Name: ExtraTreesClassifier , Val auc score: 0.99975
Model Name: GradientBoostingClassifier , Val auc score: 0.99974

# 第二层将上一层预测的结果作为特征
clf = GradientBoostingClassifier(learning_rate=0.02, subsample=0.5, max_depth=6, n_estimators=30)
clf.fit(dataset_blend_train, y)
y_submission = clf.predict_proba(dataset_blend_test)[:, 1]


print("Linear stretch of predictions to [0,1]")
y_submission = (y_submission - y_submission.min()) / (y_submission.max() - y_submission.min())
print("stack result")
print("val auc Score: %f" % (roc_auc_score(y_predict, y_submission)))
Linear stretch of predictions to [0,1]
stack result
val auc Score: 0.999617

Blending

# 切分训练数据集为d1,d2两部分
X_d1, X_d2, y_d1, y_d2 = train_test_split(X_train, y_train, test_size=0.5, random_state=2017)
dataset_d1 = np.zeros((X_d2.shape[0], len(clfs)))
dataset_d2 = np.zeros((X_test.shape[0], len(clfs)))
# 第一层
for j, clf in enumerate(clfs):
    '''依次训练各个单模型'''
    # print(j, clf)
    '''使用第1个部分作为预测,第2部分来训练模型,获得其预测的输出作为第2部分的新特征。'''
    # X_train, y_train, X_test, y_test = X[train], y[train], X[test], y[test]
    clf.fit(X_d1, y_d1)
    y_submission = clf.predict_proba(X_d2)[:, 1]
    dataset_d1[:, j] = y_submission
    '''对于测试集,直接用这k个模型的预测值作为新的特征。'''
    dataset_d2[:, j] = clf.predict_proba(X_test)[:, 1]
    print("Model Name: {0:<30},  Val auc score: {1:.5f}".format(clf.__class__.__name__, 
                                                                roc_auc_score(y_test, dataset_d2[:, j])))
# 第二层

'''融合使用的模型'''
# clf = LogisticRegression()
clf = GradientBoostingClassifier(learning_rate=0.02, subsample=0.5, max_depth=6, n_estimators=30)
clf.fit(dataset_d1, y_d2)
y_submission = clf.predict_proba(dataset_d2)[:, 1]

print('----------')
print("Linear stretch of predictions to [0,1]")
y_submission = (y_submission - y_submission.min()) / (y_submission.max() - y_submission.min())
print("blend result")
print("val auc Score: %f" % (roc_auc_score(y_predict, y_submission)))

打印结果:
Model Name: RandomForestClassifier , Val auc score: 0.99903
Model Name: RandomForestClassifier , Val auc score: 0.99927
Model Name: ExtraTreesClassifier , Val auc score: 0.99944
Model Name: ExtraTreesClassifier , Val auc score: 0.99938
Model Name: GradientBoostingClassifier , Val auc score: 0.99871
----------
Linear stretch of predictions to [0,1]
blend result
val auc Score: 0.999272

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NLP_wendi

谢谢您的支持。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值