集成学习stacking

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/winycg/article/details/84032459

参考链接:https://blog.csdn.net/willduan1/article/details/73618677

stacking

Stacking先从初始数据集训练出初级学习器,将初级学习器的输出当作特征构成新数据集,利用新数据集再训练次级学习器(meta-learner)。初级学习器通常使用不同的学习算法。
训练阶段,若直接用初级学习器的训练集来产生次级训练集,过拟合风险过大,因此一般使用交叉验证的方式,用初级学习器未使用的样本来产生次级学习器的训练器。以k折交叉验证为例,对某一个算法使用交叉验证,将k个作为验证集的部分的输出组合起来作为次级训练集的特征。过程如下:
在这里插入图片描述
次级学习器的输入属性表示和次级学习算法对Stacking集成的泛化性能有很大影响。有研究表明,将初级学习器的输出类概率作为次级学习器的输入特征,用多响应线性回归(Multi-response Linear Regression)作为次级学习算法效果较好。

使用mlxtend实现stacking

参考链接:http://rasbt.github.io/mlxtend/
mlxtend帮助文档:https://sebastianraschka.com/pdf/software/mlxtend-latest.pdf
mlxtend是一个机器学习库,里面包含了一些机器学习的包和可视化函数等等,其中包括了sklearn中没有的stacking操作。文档从88页开始讲的stacking相关的部分。
通过stacking产生的特征可以分为多种形式:
(以下例子来自官方文档),下面的例子全部为不带交叉验证时初始学习器学习到的特征,如果使用交叉验证,可以将StackingClassifier都变为StackingCVClassifier即可。
(1)将初级分类器产生的类别标签作为新特征
使用KNN,朴素贝叶斯,随机森林作为初级分类器,LR作为次级分类器。

from sklearn import datasets

iris = datasets.load_iris()
X, y = iris.data[:, 1:3], iris.target

from sklearn import model_selection
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 StackingClassifier


clf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()
lr = LogisticRegression()
sclf = StackingClassifier(classifiers=[clf1, clf2, clf3],
                          meta_classifier=lr)

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

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

输出:

Accuracy: 0.91 (+/- 0.01) [KNN]
Accuracy: 0.91 (+/- 0.06) [Random Forest]
Accuracy: 0.92 (+/- 0.03) [Naive Bayes]
Accuracy: 0.95 (+/- 0.03) [StackingClassifier]

可视化代码:

import matplotlib.pyplot as plt
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',
    'StackingClassifier'],
    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()

在这里插入图片描述
(2)将初级分类器产生的输出类概率作为新特征
对于输出概率,有两种不同的处理方式。假设有2个初级分类器和3个类别输出概率: p 1 = [ 0.2 , 0.5 , 0.3 ] , p 2 = [ 0.3 , 0.4 , 0.4 ] p1=[0.2, 0.5, 0.3],p2=[0.3,0.4,0.4]
如果average_probas=True,则对分类器的结果求平均,得到: p = [ 0.25 , 0.45 , 0.35 ] p=[0.25,0.45,0.35]
如果average_probas=False,则分类器的所有结果都保留作为新的特征,这种方法是推荐的方法 p = [ 0.2 , 0.5 , 0.3 , 0.3 , 0.4 , 0.4 ] p=[0.2, 0.5, 0.3,0.3,0.4,0.4]

sclf = StackingClassifier(classifiers=[clf1, clf2, clf3],
                          use_probas=True,
                          average_probas=False,
                          meta_classifier=lr)

输出:

Accuracy: 0.91 (+/- 0.01) [KNN]
Accuracy: 0.91 (+/- 0.06) [Random Forest]
Accuracy: 0.92 (+/- 0.03) [Naive Bayes]
Accuracy: 0.94 (+/- 0.03) [StackingClassifier]

(3)初级分类器采用不同的训练集子集来训练
需要结合sklearn中的pipeline和ColumnSelector来实现

from sklearn.datasets import load_iris
from mlxtend.classifier import StackingClassifier
from mlxtend.feature_selection import ColumnSelector
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression

iris = load_iris()
X = iris.data  # (150,4)
y = iris.target

pipe1 = make_pipeline(ColumnSelector(cols=(0, 2)),  # 选择第0,2列特征
                      LogisticRegression())
pipe2 = make_pipeline(ColumnSelector(cols=(1, 2, 3)),  # 选择第1,2,3列特征
                      LogisticRegression())

sclf = StackingClassifier(classifiers=[pipe1, pipe2],
                          meta_classifier=LogisticRegression())

sclf.fit(X, y)

猜你喜欢

转载自blog.csdn.net/winycg/article/details/84032459