Stacking集成学习在各类机器学习竞赛当中得到了广泛的应用,尤其是在结构化的机器学习竞赛当中表现非常好。今天我们就来介绍下stacking这个在机器学习模型融合当中的大杀器的原理。并在博文的后面附有相关代码实现。

总体来说,stacking集成算法主要是一种基于“标签”的学习,有以下的特点:

  用法:模型利用交叉验证,对训练集进行预测,从而实现二次学习

  优点:可以结合不同的模型

  缺点:增加了时间开销,容易造成过拟合

  关键点:模型如何进行交叉训练?

下面我们来看看stacking的具体原理是如何进行实现的,stacking又是如何实现交叉验证和训练的。

一.使用单个机器学习模型进行stacking

第一种stacking的方法,为了方便大家理解,因此只使用一个机器学习模型进行stacking。stacking的方式如下图所示:

我们可以边看图边理解staking过程。我们先看training data,也就是训练数据(训练集)。我们使用同一个机器学习model对训练数据进行了5折交叉验证(当然在实际进行stacking的时候,你也可以使用k折交叉验证,k等于多少都可以,看你自己,一般k=5或者k=10,k=5就是五折交叉验证),也就是每次训练的时候,将训练数据拆分成5份。其中四份用于训练我们的模型,另外剩下的一份将训练好的模型,在这部分上对数据进行预测predict出相应的label。由于使用了5折交叉验证,这样不断训练,一共经过5次交叉验证,我们就产生了模型对当前训练数据进行预测的一列label。而这些label也可以当作我们的新的训练特征,将预测出来的label作为一列新的特征插入到我们的训练数据当中。

插入完成后,将我们新的tranning set再次进行训练,得到我们新,也是最后的model,也就是图中的model6。这样就完成了第一次stacking,对于testing set而言,我们使用model 1/2/3/4/5分别对图中下面所对应的testing data进行预测,然后得到testing set的新的一列feature,或者称之为label。

这样,我们就完成了一次stacking的过程。

然而,我们不仅可以stacking仅仅一次,我们还可以对当前训练出来的模型再次进行stacking,也就是重复刚才的过程,这样我们的训练集又会多出一个新的一列,每stacking一次,数据就会多出一列。但是如果仅仅用一个模型进行stakcing,效果往往没有那么好,因为这样我们的数据和模型并不具备多样性,也就无法从数学上保证我们数据的“独立性”,树模型比如bagging能够达到很好的效果,包括我们的stacking,模型的多样性越大,差异越大,集成之后往往会得到更好的收益,这个在数学上有严格的证明的,可以通过binomial distribution的方法来证明,大家了解即可。

因此这里介绍,如何使用多个机器学习模型进行stacking,这种方法在机器学习竞赛当中也更加常见。

二.使用多个机器模型进行stacking

使用多个机器学习模型进行stacking其实就是每使用一个模型进行训练,就多出一个训练集的feature,也就是将训练集多出一列。如下图所示:

在这张图当中,我们使用了xgboost,lightgbm,random forest分别对同一个数据集做了训练,xgboost训练完后,trainning set多出一列,lightgbm训练完成后,又多出一列random forest训练完成后,又多出一列。因此我们的traning set一共多出了三列。这样我们再用多出这三列的数据重新使用新的机器学习模型进行训练,就可以得到一个更加完美的模型啦!这也就是多个不同机器学习模型进行stacking的原理。同时 ,我们也可以对多个机器学习模型进行多次堆叠,也就是进行多次stakcing的操作。

三.stacking模型代码实现(基本实现)

由于sklearn并没有直接对Stacking的方法,因此我们需要下载mlxtend工具包(pip install mlxtend)

# 1. 简单堆叠3折CV分类,默认为3,可以使用cv=5改变为5折cv分类
from sklearn import datasetsiris = 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 StackingCVClassifierRANDOM_SEED = 42clf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=RANDOM_SEED)
clf3 = GaussianNB()
lr = LogisticRegression()# Starting from v0.16.0, StackingCVRegressor supports
# `random_state` to get deterministic result.
sclf = StackingCVClassifier(classifiers=[clf1, clf2, clf3],  # 第一层分类器meta_classifier=lr,   # 第二层分类器,并非表示第二次stacking,而是通过logistic regression对新的训练特征数据进行训练,得到predicted labelrandom_state=RANDOM_SEED)print('3-fold cross validation:\n')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))

输出:

3-fold cross validation:Accuracy: 0.91 (+/- 0.01) [KNN]
Accuracy: 0.95 (+/- 0.01) [Random Forest]
Accuracy: 0.91 (+/- 0.02) [Naive Bayes]
Accuracy: 0.93 (+/- 0.02) [StackingClassifier]

画出决策边界:

# 我们画出决策边界
from mlxtend.plotting import plot_decision_regions
import matplotlib.gridspec as gridspec
import itertoolsgs = 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()

如果想要更加清楚地指定,我们的多个机器学习学到的数据输出的概率(假设我们的label为概率),是否会被平均,按照多个模型的平均值来变成我们的训练数据的列(个人不太推荐这么干,因为一旦平均之后,其实就缺失了一些模型差异性的信息和特征,这样在某些情况下反而得不太好的结果)。因此我们使用以下的代码:

# 使用概率作为元特征
clf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()
lr = LogisticRegression()sclf = StackingCVClassifier(classifiers=[clf1, clf2, clf3],use_probas=True,  average_probas = False,meta_classifier=lr,random_state=42)
#average_probas = False 表示不对概率进行平均print('3-fold cross validation:\n')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))            

输出:

3-fold cross validation:Accuracy: 0.91 (+/- 0.01) [KNN]
Accuracy: 0.95 (+/- 0.01) [Random Forest]
Accuracy: 0.91 (+/- 0.02) [Naive Bayes]
Accuracy: 0.95 (+/- 0.02) [StackingClassifier]

四.Stacking配合grid search网格搜索实现超参数调整

# 3. 堆叠5折CV分类与网格搜索(结合网格搜索调参优化)
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
from mlxtend.classifier import StackingCVClassifier# Initializing modelsclf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=RANDOM_SEED)
clf3 = GaussianNB()
lr = LogisticRegression()sclf = StackingCVClassifier(classifiers=[clf1, clf2, clf3], meta_classifier=lr,random_state=42)params = {'kneighborsclassifier__n_neighbors': [1, 5],'randomforestclassifier__n_estimators': [10, 50],'meta_classifier__C': [0.1, 10.0]}grid = GridSearchCV(estimator=sclf, param_grid=params, cv=5,refit=True)
grid.fit(X, y)cv_keys = ('mean_test_score', 'std_test_score', 'params')for r, _ in enumerate(grid.cv_results_['mean_test_score']):print("%0.3f +/- %0.2f %r"% (grid.cv_results_[cv_keys[0]][r],grid.cv_results_[cv_keys[1]][r] / 2.0,grid.cv_results_[cv_keys[2]][r]))print('Best parameters: %s' % grid.best_params_)
print('Accuracy: %.2f' % grid.best_score_)

输出:

0.947 +/- 0.03 {'kneighborsclassifier__n_neighbors': 1, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 10}
0.933 +/- 0.02 {'kneighborsclassifier__n_neighbors': 1, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 50}
0.940 +/- 0.02 {'kneighborsclassifier__n_neighbors': 1, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 10}
0.940 +/- 0.02 {'kneighborsclassifier__n_neighbors': 1, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 50}
0.953 +/- 0.02 {'kneighborsclassifier__n_neighbors': 5, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 10}
0.953 +/- 0.02 {'kneighborsclassifier__n_neighbors': 5, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 50}
0.953 +/- 0.02 {'kneighborsclassifier__n_neighbors': 5, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 10}
0.953 +/- 0.02 {'kneighborsclassifier__n_neighbors': 5, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 50}
Best parameters: {'kneighborsclassifier__n_neighbors': 5, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 10}
Accuracy: 0.95

得到最后最好的参数如上。当然如果,你想要更好的搜索参数,可以使用贝叶斯搜索参数,或者随机参数搜索法,对参数进行搜索。

结语:在这篇博文当中,我论述了stacking的原理和python的代码实现,希望大家读完后会有收获。如果觉得看了有收获的同学,请在下方点个赞,推荐一下,谢谢啦!

参考文献:

1.https://github.com/Geeksongs/ensemble-learning/blob/main/CH5-%E9%9B%86%E6%88%90%E5%AD%A6%E4%B9%A0%E4%B9%8Bblending%E4%B8%8Estacking/Stacking.ipynb

2.https://www.cnblogs.com/Christina-Notebook/p/10063146.html

【集成学习】:Stacking原理以及Python代码实现相关推荐

  1. 随机森林分类算法python代码_随机森林的原理及Python代码实现

    原标题:随机森林的原理及Python代码实现 最近在做kaggle的时候,发现随机森林这个算法在分类问题上效果十分的好,大多数情况下效果远要比svm,log回归,knn等算法效果好.因此想琢磨琢磨这个 ...

  2. CRC爆破png图片宽度和高度原理以及python代码

    CRC爆破png图片宽度和高度原理以及python代码 文章目录 CRC爆破png图片宽度和高度原理以及python代码 1.PNG图片的格式 2.CRC 3.Python爆破图片宽度和高度 参考文章 ...

  3. 模式识别中利用二型势函数法求解非线性分类器的原理以及python代码实现

    前言 在学校的深度学习实验过程中,由于要求实现非线性分类器的势函数实验中给出的例程代码是matlab语言的(ps:自从电脑被偷了以后,新电脑没有装matlab),我便想到用python实现非线性分类器 ...

  4. python原理_强化学习:原理与Python实现

    强化学习:原理与Python实现 作者:肖智清 著 出版日期:2019年08月 文件大小:17.18M 支持设备: ¥60.00 适用客户端: 言商书局 iPad/iPhone客户端:下载 Andro ...

  5. 一文看懂Stacking!(含Python代码)

    一文看懂Stacking!(含Python代码) https://mp.weixin.qq.com/s/faQNTGgBZdZyyZscdhjwUQ 转载于:https://www.cnblogs.c ...

  6. 弗雷歇距离的原理及python代码实现(动态规划)

    弗雷歇距离的原理及python代码实现(动态规划) 在网上看了很多关于弗雷歇距离的介绍,结合自己的理解,出一版更通俗易懂.更清晰具体的解释. 最简单的解释自然是最短狗绳长度,但我将从另一个角度来解释它 ...

  7. 集成学习-模型融合学习笔记(附Python代码)

    1 集成学习概述 集成学习(Ensemble Learning)是一种能在各种的机器学习任务上提高准确率的强有力技术,其通过组合多个基分类器(base classifier)来完成学习任务.基分类器一 ...

  8. 集成学习——bagging原理及分析

    bagging原理   与投票法不同的是,Bagging不仅仅集成模型最后的预测结果,同时采用一定策略来影响基模型训练,保证基模型可以服从一定的假设.在上一章中我们提到,希望各个模型之间具有较大的差异 ...

  9. 【机器学习】集成学习Stacking

    上半部分是用一个基础模型进行5折交叉验证,如:用XGBoost作为基础模型Model1,5折交叉验证就是先拿出四折作为training data,另外一折作为testing data.注意:在stac ...

最新文章

  1. [转]使用 C 编写 Lua 模块
  2. 单击CheckBox,全选GridView中所有CheckBox
  3. R--线性回归诊断(一)
  4. 栈的C语言案例,堆栈实例代码(C语言)
  5. c语言指针数组课件,C语言指针与数组教程课件.ppt
  6. 【翻译】如何获取正在运行的StreamInsight实例版本号?
  7. Android方法的概括,Android_Android中startService基本使用方法概述,Android中有两种主要方式使用Ser - phpStudy...
  8. 中缀表达式变后缀分析
  9. LVDT位移传感器的构成原理及特点
  10. uniapp 使用本地数据库
  11. 恒凯USB数据采集卡在国产麒麟操作系统下的应用(二)Python环境设置及数据采集实验
  12. 为什么网站要使用手机验证码?
  13. 1588 1-Step 和 2-Step PTP 之间有什么区别?
  14. Python期末考试题库
  15. 非单射一致性和单射一致性的概念辨析
  16. 连接板卡的时候,如何避免每次都设置ip
  17. 某网站电商运营数据分析案例
  18. XML 是一种元语言, 可以用它来描述其他语言。
  19. 面经|缺失值填补的7种方法(使用场景+Python代码)
  20. CSDN年度征文 | 你好!2023

热门文章

  1. expander菜单控件_Expander 类 (System.Windows.Controls) | Microsoft Docs
  2. sony降级xp,超级简单,集成sata,可以u盘pe安装
  3. cartographer之pose_extrapolator
  4. Shell——quan——内置变量
  5. vn的可变数据类型_casting - 是否有任何编程语言可以禁止对返回类型进行类转换? - SO中文参考 - www.soinside.com...
  6. android8-java-代码中休眠唤醒-sleep/wake
  7. java开发中常用的Git命令详解
  8. 10款常见MySQL高可用方案选型解读
  9. 锐龙r5 6600h和酷睿i5 12500h处理器哪个好 r56600h和i512500h差多少
  10. LocalDateTime去掉T,JSONField失效