前言

Stacking核心思想

stacking严格来说并不是一种算法,而是精美而又复杂的,对模型集成的一种策略。
Stacking集成算法可以理解为一个两层的集成,第一层含有多个基础分类器,把预测的结果(元特征)提供给第二层, 而第二层的分类器通常是逻辑回归,他把一层分类器的结果当做特征做拟合输出预测结果。

训练过程(使用K折交叉验证)

  1. 划分训练集和测试集,并将训练集进一步随机且大致均匀的分为 K 份,交叉验证过程中,随机选(K-1) 份为训练集,剩余1份为验证集

  2. 选择基模型,在划分后的训练集上进行交叉验证训练模型,同时在测试集上进行预测

  • a)训练基模型。利用 (K-1) 份训练数据训练模型,用训练的模型在验证集上进行预测

  • b) 在此过程进行的同时,利用相同的 4 份数据训练出的模型,在测试集上预测;如此重复 K 次,将验证集上的 K 次结果按行叠加为 1 列,将测试集上的 K 次结果取均值融合为 1 列

  1. 使用 多 个分类器重复 2 过程。将分别得到 k 列验证集的预测结果,k 列测试集的预测结果

  2. 训练 3 过程得到的数据。将 k 列验证集的预测结果和训练集真实 label 构成次级模型的训练集(次级训练集),将 k 列测试集预测结果作为测试集,训练第二层模型

## 1. 简单堆叠 3 折交叉验证分类
from sklearn import datasetsiris = datasets.load_iris()
X, y = iris.data[:, 1:3], iris.targetfrom 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 = 1clf1 = 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=RANDOM_SEED)print('3-fold cross validation: \n')for clf, label in zip([clf1, clf2, clf3, sclf], ['KNN', 'RF', '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) [RF]
Accuracy: 0.91 (+/- 0.02) [Naive_Bayes]
Accuracy: 0.94 (+/- 0.03) [StackingClassifier]
## 画出决策边界
from mlxtend.plotting import plot_decision_regions
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec # 指定放置子图的网格的规格
import itertools  # 创建循环用迭代器的函数模块gs = gridspec.GridSpec(2, 2)# 分为2行2列
fig = plt.figure(figsize=(10, 8))
for clf, label, grd in zip([clf1, clf2, clf3, sclf], ['KNN', 'RF', 'Naive_Bayes','StackingClassifier'], # 笛卡尔积,repeat 指定重复生成序列的次数,在这里产生(0,0)(0,1)(1, 0)(1,1)itertools.product([0, 1], repeat=2) # 在gs的四个网格坐标中画决策边界):clf.fit(X, y)ax = plt.subplot(gs[grd[0], grd[1]])fig = plot_decision_regions(X=X, y=y, clf=clf)plt.title(label)
plt.show()

# 2.使用概率作为元特征
clf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()
lr = LogisticRegression()sclf = StackingCVClassifier(classifiers=[clf1, clf2, clf3],use_probas=True,  # meta_classifier=lr,random_state=42)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]
# 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.933 +/- 0.03 {'kneighborsclassifier__n_neighbors': 1, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 10}
0.940 +/- 0.02 {'kneighborsclassifier__n_neighbors': 1, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 50}
0.927 +/- 0.02 {'kneighborsclassifier__n_neighbors': 1, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 10}
0.927 +/- 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
# 如果打算多次使用回归算法,需要在参数网格中添加一个附加的数字后缀
from sklearn.model_selection import GridSearchCV# Initializing modelsclf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=RANDOM_SEED)
clf3 = GaussianNB()
lr = LogisticRegression()sclf = StackingCVClassifier(classifiers=[clf1, clf1, clf2, clf3], meta_classifier=lr,random_state=RANDOM_SEED)params = {'kneighborsclassifier-1__n_neighbors': [1, 5], # 数字后缀'kneighborsclassifier-2__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.940 +/- 0.03 {'kneighborsclassifier-1__n_neighbors': 1, 'kneighborsclassifier-2__n_neighbors': 1, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 10}
0.933 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 1, 'kneighborsclassifier-2__n_neighbors': 1, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 50}
0.933 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 1, 'kneighborsclassifier-2__n_neighbors': 1, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 10}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 1, 'kneighborsclassifier-2__n_neighbors': 1, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 50}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 1, 'kneighborsclassifier-2__n_neighbors': 5, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 10}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 1, 'kneighborsclassifier-2__n_neighbors': 5, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 50}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 1, 'kneighborsclassifier-2__n_neighbors': 5, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 10}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 1, 'kneighborsclassifier-2__n_neighbors': 5, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 50}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 5, 'kneighborsclassifier-2__n_neighbors': 1, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 10}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 5, 'kneighborsclassifier-2__n_neighbors': 1, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 50}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 5, 'kneighborsclassifier-2__n_neighbors': 1, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 10}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 5, 'kneighborsclassifier-2__n_neighbors': 1, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 50}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 5, 'kneighborsclassifier-2__n_neighbors': 5, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 10}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 5, 'kneighborsclassifier-2__n_neighbors': 5, 'meta_classifier__C': 0.1, 'randomforestclassifier__n_estimators': 50}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 5, 'kneighborsclassifier-2__n_neighbors': 5, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 10}
0.953 +/- 0.02 {'kneighborsclassifier-1__n_neighbors': 5, 'kneighborsclassifier-2__n_neighbors': 5, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 50}
Best parameters: {'kneighborsclassifier-1__n_neighbors': 1, 'kneighborsclassifier-2__n_neighbors': 1, 'meta_classifier__C': 10.0, 'randomforestclassifier__n_estimators': 50}
Accuracy: 0.95
# 4.在不同特征子集上运行的分类器的堆叠
##不同的1级分类器可以适合训练数据集中的不同特征子集。以下示例说明了如何使用scikit-learn管道和ColumnSelector:
from sklearn.datasets import load_iris
from mlxtend.classifier import StackingCVClassifier
from mlxtend.feature_selection import ColumnSelector
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegressioniris = load_iris()
X = iris.data
y = iris.targetpipe1 = make_pipeline(ColumnSelector(cols=(0, 2)),  # 选择第0,2列LogisticRegression())
pipe2 = make_pipeline(ColumnSelector(cols=(1, 2, 3)),  # 选择第1,2,3列LogisticRegression())sclf = StackingCVClassifier(classifiers=[pipe1, pipe2], meta_classifier=LogisticRegression(),random_state=42)sclf.fit(X, y)
StackingCVClassifier(classifiers=[Pipeline(memory=None,steps=[('columnselector',ColumnSelector(cols=(0, 2),drop_axis=False)),('logisticregression',LogisticRegression(C=1.0,class_weight=None,dual=False,fit_intercept=True,intercept_scaling=1,l1_ratio=None,max_iter=100,multi_class='auto',n_jobs=None,penalty='l2',random_state=None,solver='lbfgs',tol=0.0...fit_intercept=True,intercept_scaling=1,l1_ratio=None,max_iter=100,multi_class='auto',n_jobs=None,penalty='l2',random_state=None,solver='lbfgs',tol=0.0001, verbose=0,warm_start=False),n_jobs=None, pre_dispatch='2*n_jobs', random_state=42,shuffle=True, store_train_meta_features=False,stratify=True, use_clones=True,use_features_in_secondary=False, use_probas=False,verbose=0)
# 5.ROC曲线 decision_function
### 像其他scikit-learn分类器一样,它StackingCVClassifier具有decision_function可用于绘制ROC曲线的方法。
### 请注意,decision_function期望并要求元分类器实现decision_function。
from sklearn import model_selection
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from mlxtend.classifier import StackingCVClassifier
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifieriris = datasets.load_iris()
X, y = iris.data[:, [0, 1]], iris.target# Binarize the output
y = label_binarize(y, classes=[0, 1, 2])
n_classes = y.shape[1]RANDOM_SEED = 42X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=RANDOM_SEED)clf1 =  LogisticRegression()
clf2 = RandomForestClassifier(random_state=RANDOM_SEED)
clf3 = SVC(random_state=RANDOM_SEED)
lr = LogisticRegression()sclf = StackingCVClassifier(classifiers=[clf1, clf2, clf3],meta_classifier=lr)# Learn to predict each class against the other
classifier = OneVsRestClassifier(sclf)
y_score = classifier.fit(X_train, y_train).decision_function(X_test)# Compute ROC curve and ROC area for each class
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(n_classes):fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i])roc_auc[i] = auc(fpr[i], tpr[i])# Compute micro-average ROC curve and ROC area
fpr["micro"], tpr["micro"], _ = roc_curve(y_test.ravel(), y_score.ravel())
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])plt.figure()
lw = 2
plt.plot(fpr[2], tpr[2], color='darkorange',lw=lw, label='ROC curve (area = %0.2f)' % roc_auc[2])
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()

参考资料

[1] Datawhale,[机器学习集成学习与模型融合(基于python)](https://github.com/datawhalechina/team-learning-data-

Datawhale集成学习:Stacking 算法与实战相关推荐

  1. 集成学习-Stacking算法

    Stacking (堆叠)的基本思想 Stacking是通过一个元分类器或者元回归器来整合多个分类模型或回归模型的集成学习技术.基础模型利用整个训练集做训练,元模型将基础模型的特征作为特征进行训练. ...

  2. 机器学习--集成学习Stacking算法23

    什么是Stacking 使用多个不同的分类器对训练集进预测,把预测 得到的结果作为一个次级分类器的输入.次级分 类器的输出是整个模型的预测结果. Stacking需要训练两层分类器,第一层的初级分类器 ...

  3. 机器学习实战-54: 集成学习分类算法(ada-boost)

    集成学习分类算法 深度学习原理与实践(开源图书)-总目录,建议收藏,告别碎片阅读! 集成学习分类算法(ada-boost)属于监督学习算法.常用分类算法包括:逻辑回归(Logistic Regress ...

  4. 【组队学习】【23期】Datawhale集成学习(上)

    集成学习(上) 开源内容:https://github.com/datawhalechina/team-learning-data-mining/tree/master/IntegratedLearn ...

  5. 【机器学习】集成学习及算法详解

    集成学习及算法详解 前言 一.随机森林算法原理 二.随机森林的优势与特征重要性指标 1.随机森林的优势 2.特征重要性指标 三.提升算法概述 四.堆叠模型简述 五.硬投票和软投票 1.概念介绍 2.硬 ...

  6. 机器学习 - [集成学习]Bagging算法的编程实现

    机器学习 - [集成学习] Bagging算法的编程实现 李俊才 的 CSDN 博客:https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343 ...

  7. 深度学习:算法到实战

    本文是学习专知课程<深度学习:算法到实战>的个人笔记. 第一讲 绪论 1.1 人工智能和机器学习概述 (1)人工智能(Artificial Intelligence)        使一部 ...

  8. 【AdaBoost算法】集成学习——AdaBoost算法实例说明

    [AdaBoost算法]集成学习--AdaBoost算法实例说明 AdaBoost算法是数据挖掘十大算法之一,但是部分参考书上只给了该算法的数学推导过程,具体的流程并未详细举例加以解释,因此不利于学习 ...

  9. Datawhale集成学习笔记:XGBOOST算法

    引用:Datawhale XGBoost算法 XGBoost是陈天奇等人开发的一个开源机器学习项目,高效地实现了GBDT算法并进行了算法和工程上的许多改进,被广泛应用在Kaggle竞赛及其他许多机器学 ...

最新文章

  1. 从无到有-在create-react-app基础上接入react-router、redux-saga
  2. SQL判断文件是否存在
  3. devcon的测试 尝试使用devcon命令重置Intel Realsense D435摄像头 USB
  4. 2021 CVPR论文解读征集令
  5. html列表滑动字母索引,js实现做通讯录的索引滑动显示效果和滑动显示锚点效果...
  6. scala 函数中嵌套函数_如何在Scala中将函数转换为部分函数?
  7. iphone微信美颜插件_iOS13.5 插件分享
  8. 硅谷独角兽公司的监控系统长啥样?
  9. php逻辑难是难在sql,[实验吧] 所有web writeup
  10. AngularJS学习笔记之directive—scope选项与绑定策略
  11. aws rds监控慢sql_AWS RDS SQL Server中的高级Windows身份验证配置
  12. 监控视频异常检测数据集整理
  13. Winform控件学习笔记【第四天】——WebBrowser
  14. dota2 自定义官方服务器,DOTA2官网更新:服务器扩容 首部官方漫画发布
  15. python打开浏览器并截图_使用python实现网页截图的两种方式
  16. 使用交易API将产品添加到您的eBay商店
  17. indesign如何画弧线_InDesign钢笔工具怎么使用
  18. VUE动态展示表格字段
  19. 【数学建模】基于matlab武汉地铁2号线路线地图动态模拟【含Matlab源码 1092期】
  20. 网络-4 【http状态码、accept、Content-Type】

热门文章

  1. MCMC算法--Gibbs采样2:多元高斯分布的边际分布与条件分布推导
  2. 中消协点评霸王条款:商品房合同警惕九大陷阱
  3. Wapiti是什么以及使用教程
  4. win10系统,磁盘目录上出现感叹号和一把锁
  5. Vue3为什么要使用组合式API——Vue3的组合式API和Vue2的选项式API的优缺点
  6. FileItem中文名字乱码问题的解决
  7. 素数基本(埃氏筛法/线性筛法)
  8. linux下apache配置文件测试,重启 Apache 服务器及测试配置
  9. Brave TAH的硬件设计及制作-Part2
  10. java set怎么初始化_Java Set的初始化方法