集成学习(下)Stacking集成学习方法原理与实战

导言

上次我们介绍了Blending算法的优缺点,而Stack算法的出现就是解决了Blending的缺点并进行改进。

原理

简单来说,Stacking就是当用初始训练数据学习出若干个基学习器后,将这几个学习器的预测结果作为新的训练集,来学习一个新的学习器。我们举个例子来具体感受Stacking处理问题的细节。
(1)将所有数据集生成测试集和训练集(假如训练集为10000条,测试集为2500条),那么第一层会进行5折交叉验证(折数可以自己定),使用训练集中的8000条作为训练集,剩余2000行作为验证集。
(2)通过5折交叉验证,我们可以在2000行的验证集得到52000个的预测结果,在2500条测试集得到5 2500条测试集的预测结果。
(3)将验证集的5* 2000条预测结果拼接成10000行长的矩阵,标记为 A 1 A_{1} A1,而对于5* 2500行的测试集的预测结果进行加权平均,得到一个2500一列的矩阵,标记为 B 1 B_{1} B1
(4)在(3)中,一个基模型在数据集上的预测结果为 A 1 A_{1} A1 B 1 B_{1} B1 ,这样当我们对3个基模型进行集成的话,相于得到了 A 1 A_{1} A1 B 1 B_{1} B1 A 2 A_{2} A2 B 2 B_{2} B2 A 3 A_{3} A3 B 3 B_{3} B3六个矩阵。将 A 1 A_{1} A1、A_{2} 、 、 A_{3}$ 并列(横向拼接)在一起成10000行3列的矩阵作为第二层的training data, B 1 B_{1} B1 B 2 B_{2} B2 B 3 B_{3} B3合并在一起成2500行3列的矩阵作为第二层的testing data。
(5)第二层的训练便基于每个基础模型的预测结果作为特征(三个特征),从而得到最后的预测结果。

Stacking实战

为了方便读者复现代码,还是优先考虑sklearn自带数据集,本次实战采用乳腺癌数据。

导入需要的库
from sklearn.datasets import load_breast_cancer
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
导入数据
## 读取数据
cancer = load_breast_cancer()
X = cancer.data
y = cancer.target
print('data shape: {0}; no. positive: {1}; no. negative: {2}'.format(
    X.shape, y[y==1].shape[0], y[y==0].shape[0]))
实现一:简单堆叠3折CV分类
# 1. 简单堆叠3折CV分类
RANDOM_SEED = 42

clf1 = 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,   # 第二层分类器
                            random_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))

在这里插入图片描述

实现二:使用概率作为元特征
# 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:')

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))

在这里插入图片描述

实现三:堆叠5折CV分类与网格搜索最优参数

注意:网格搜索在大数据集上是非常耗时

# 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 models

clf1 = 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_)

在这里插入图片描述

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值