2021-05-12

1. Stacking模型

针对上一章节Blending对数据集的处理的方法,我们知道:Blending在集成的过程中只会用到验证集的数据,对数据实际上是一个很大的浪费。为了解决这个问题,我们详细分析下Blending到底哪里出现问题并如何改进。在Blending中,我们产生验证集的方式是使用分割的方式,产生一组训练集和一组验证集,这让我们联想到交叉验证的方式。顺着这个思路,我们对Stacking进行建模(如下图)
在这里插入图片描述stacking 的框架结构与运行过程:
1.选择基模型。我们可以有 xgboost,lightGMB,RandomForest,SVM,ANN,KNN, LR 等等你能想到的各种基本算法模型。

from sklearn import datasets

iris = datasets.load_iris()
X, y = iris.data[:, 1:3], iris.target
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB 
from sklearn.ensemble import RandomForestClassifier
from mlxtend.classifier import StackingCVClassifier

RANDOM_SEED = 42

clf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=RANDOM_SEED)
clf3 = GaussianNB()
lr = LogisticRegression()

2.将所有数据集生成测试集和训练集(假如训练集为10000,测试集为2500行),之后把训练集分为不交叉的五份。那么上层会进行5折交叉检验,使用训练集中的8000条作为训练集,剩余2000行作为验证集(橙色)。
3.每次验证相当于使用了蓝色的8000条数据训练出一个模型,使用模型对验证集进行验证得到2000条数据,并对测试集进行预测,得到2500条数据,这样经过5次交叉检验,可以得到中间的橙色的5*2000条验证集的结果(相当于每条数据的预测结果),5 *2500条测试集的预测结果。

# Starting from v0.16.0, StackingCVRegressor supports
# `random_state` to get deterministic result.
sclf = StackingCVClassifier(classifiers=[clf1, clf2, clf3],  # 第一层分类器
                            meta_classifier=lr,   # 第二层分类器
                            random_state=RANDOM_SEED)

print('3-fold cross validation:\n')

4.接下来会将验证集的5 2000条预测结果拼接成10000行长的矩阵,标记为 A1 ,而对于5 2500行的测试集的预测结果进行加权平均,得到一个2500一列的矩阵,标记为 B1 。
上面得到一个基模型在数据集上的预测结果 A1 、 B1 ,这样当我们对3个基模型进行集成的话,相于得到了 A1 、 A2 、 A3 、 B1 、 B2 、 B3 六个矩阵。
5.之后我们会将 A1 、 A2 、 A3 并列在一起成10000行3列的矩阵作为training data, B1 、 B2 、 B3 合并在一起成2500行3列的矩阵作为testing data,让下层学习器基于这样的数据进行再训练。

for clf, label in zip([clf1, clf2, clf3, sclf], ['KNN', 'Random Forest', 'Naive Bayes','StackingClassifier']):
    scores = cross_val_score(clf, X, y, cv=3, scoring='accuracy')
    print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))

6.再训练是基于每个基础模型的预测结果作为特征(三个特征),次学习器会学习训练如果往这样的基学习的预测结果上赋予权重w,来使得最后的预测最为准确

# 我们画出决策边界
from mlxtend.plotting import plot_decision_regions
import matplotlib.gridspec as gridspec
import itertools

gs = gridspec.GridSpec(2, 2)
fig = plt.figure(figsize=(10,8))
for clf, lab, grd in zip([clf1, clf2, clf3, sclf], 
                         ['KNN', 
                          'Random Forest', 
                          'Naive Bayes',
                          'StackingCVClassifier'],
                          itertools.product([0, 1], repeat=2)):
    clf.fit(X, y)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X=X, y=y, clf=clf)
    plt.title(lab)
plt.show()

使用stacking 的一些注意事项

  1. stacking 的框架设计比较复杂,对于一个基模型要训练 5 次,如果你的一个 xgb 模型要训练 2 个小时,即使在进行 stacking 的时候每折减少了五分之一的数据量,你的计算时间仍然是很可观的,加起来应该还是 8-9 小时,所以耗费时间很长(想像一下一个 stacking 框架跑一个基模型要大半天,简直太可怕)。所以建议大家在使用的时候要计算时间的耗费,或者可以改为 3 折,4 折等等;
  2. 基模型除了是不同参数的相同模型之外,比如不同参数的 xgboost,或者不同 K 值的 KNN 等等;更重要的是要尽可能的多加一些不同种类的基模型进去,也就是说所谓的模型要“跨越空间” 的概念。这样的话我们的集成结果会更加稳健,更加精确。

参考 :

  1. https://zhuanlan.zhihu.com/p/31961233.
  2. https://github.com/datawhalechina/team-learning-data-mining/tree/master/EnsembleLearning.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值