集成学习(四)——Blending和Stacking

Blending集成学习算法

简介

在这里插入图片描述

Blending集成学习方式如下:
(1) 将数据划分为训练集和测试集(test_set),其中训练集需要再次划分为训练集(train_set)和验证集(val_set);

在此步骤中,总的数据集被分成训练集(80%)和测试集(20%),在这80%的训练集中再拆分训练集(70%)和验证集(30%)。因此拆分后的数据集由三部分组成:训练集80%* 70% 、测试集20%、验证集80%* 30% 。训练集是为了训练模型,测试集是为了调整模型(调参),测试集则是为了检验模型的优度。

(2) 创建第一层的多个模型,这些模型可以使同质的也可以是异质的;
(3) 使用train_set训练步骤2中的多个模型,然后用训练好的模型预测val_set和test_set得到val_predict, test_predict1;

在2-3步中,使用训练集创建K个模型,如SVM/random forests, XGBoost等作为第一层的模型。训练好的模型将验证集输入模型进行预测,得到K组不同的输出(记作A_1,…,A_K),然后将测试集输入K个模型也得到K组输出(记作B_1,…,B_K),其中(A_i的样本数与验证集一致,B_i的样本数与测试集一致。

如果总的样本数有10000个样本,那么使用5600个样本训练了K个模型,输入验证集2400个样本得到K组2400个样本的结果A_1,…,A_K,输入测试集2000个得到K组2000个样本的结果B_1,…,B_K。

(4) 创建第二层的模型,使用val_predict作为训练集训练第二层的模型;

使用K组2400个样本的验证集结果A_1,…,A_K作为第二层分类器的特征,验证集的2400个标签为因变量,训练第二层分类器,得到2400个样本的输出。

(5) 使用第二层训练好的模型对第二层测试集test_predict1进行预测,该结果为整个测试集的结果。

将输入测试集2000个得到K组2000个样本的结果B_1,…,B_K放入第二层分类器,得到2000个测试集的预测结果。

在这里插入图片描述

示例

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use("ggplot")
%matplotlib inline
import seaborn as sns

from sklearn import datasets
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split

data,target=make_blobs(n_samples=10000, centers=2, random_state=1,cluster_std=1.0)

X_train1, X_test, y_train1, y_test=train_test_split(data,target,test_size=0.2,random_state=1)
X_train,X_val,y_train,y_val=train_test_split(X_train1,y_train1,test_size=0.3,random_state=1)

#第一层分类器
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier

clfs=[SVC(probability=True),RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'), KNeighborsClassifier()]

#第二层分类器
from sklearn.linear_model import LinearRegression
lr=LinearRegression()

#第一层的验证集结果与测试集结果

val_features=np.zeros((X_val.shape[0],len(clfs)))
test_features=np.zeros((X_test.shape[0],len(clfs)))

for i, clf in enumerate(clfs):
    clf.fit(X_train,y_train)
    val_feature = clf.predict_proba(X_val)[:, 1]
    test_feature = clf.predict_proba(X_test)[:,1]
    val_features[:,i] = val_feature
    test_features[:,i] = test_feature

# 将第一层的验证集的结果输入第二层训练第二层分类器
lr.fit(val_features,y_val)
# 输出预测的结果
from sklearn.model_selection import cross_val_score
cross_val_score(lr,test_features,y_test,cv=5)
        

array([1., 1., 1., 1., 1.])

参考

在这里插入图片描述

Stacking集成学习算法

简介

在Blending中,产生验证集的方式是使用分割的方式,产生一组训练集和一组验证集,如果采用交叉验证的方式对数据多次利用呢?
在这里插入图片描述

  1. 首先将所有数据集生成测试集和训练集(假如训练集为10000,测试集为2500行),那么上层会进行5折交叉检验,使用训练集中的8000条作为训练集,剩余2000行作为验证集(橙色)。
  2. 每次验证相当于使用了蓝色的8000条数据训练出一个模型,使用模型对验证集进行验证得到2000条数据,并对测试集进行预测,得到2500条数据,这样经过5次交叉检验,可以得到中间的橙色的5* 2000条验证集的结果(相当于每条数据的预测结果),5* 2500条测试集的预测结果。
  3. 接下来会将验证集的52000条预测结果拼接成10000行长的矩阵,标记为 𝐴1 ,而对于52500行的测试集的预测结果进行加权平均,得到一个2500一列的矩阵,标记为 𝐵1 。
  4. 上面得到一个基模型在数据集上的预测结果 𝐴1 、 𝐵1 , 这样当我们对3个基模型进行集成的话,相于得到了 𝐴1 、 𝐴2 、 𝐴3 、 𝐵1 、 𝐵2 、 𝐵3六个矩阵。
  5. 之后将 𝐴1 、 𝐴2 、 𝐴3 并列在一起成10000行3列的矩阵作为training data, 𝐵1 、𝐵2 、 𝐵3 合并在一起成2500行3列的矩阵作为testing data,让下层学习器基于这样的数据进行再训练。
  6. 再训练是基于每个基础模型的预测结果作为特征(三个特征),次学习器会学习训练如果往这样的基学习的预测结果上赋予权重w,来使得最后的预测最为准确。

示例

#3折CV分类
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()

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

3-fold cross validation:

Accuracy: 0.91 (+/- 0.01) [KNN]
Accuracy: 0.90 (+/- 0.03) [Random Forest]
Accuracy: 0.92 (+/- 0.03) [Naive Bayes]
Accuracy: 0.93 (+/- 0.02) [StackingClassifier]

#决策边界

#参考:http://rasbt.github.io/mlxtend/user_guide/plotting/plot_decision_regions/

from mlxtend.plotting import plot_decision_regions
import matplotlib.gridspec as gridspec
import itertools
import matplotlib.pyplot as plt
%matplotlib inline

gs=gridspec.GridSpec(2,2)
fig=plt.figure(figsize=(10,8))
for clf,lable,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(label)
plt.show()

在这里插入图片描述

#使用概率作为元特征

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.93 (+/- 0.05) [Random Forest]
Accuracy: 0.92 (+/- 0.03) [Naive Bayes]
Accuracy: 0.95 (+/- 0.04) [StackingClassifier]

使用第一层所有基分类器所产生的类别概率值作为meta-classfier的输入。需要在StackingClassifier 中增加一个参数设置:use_probas = True。

另外,还有一个参数设置average_probas = True,那么这些基分类器所产出的概率值将按照列被平均,否则会拼接。

例如:

基分类器1:predictions=[0.2,0.2,0.7]

基分类器2:predictions=[0.4,0.3,0.8]

基分类器3:predictions=[0.1,0.4,0.6]

1)若use_probas = True,average_probas = True,

则产生的meta-feature 为:[0.233, 0.3, 0.7]
2)若use_probas = True,average_probas = False,

则产生的meta-feature 为:[0.2,0.2,0.7,0.4,0.3,0.8,0.1,0.4,0.6]

#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


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],
             grid.cv_results_[cv_keys[2]][r]))

print('Best parameters: %s' % grid.best_params_)
print('Accuracy: %.2f' % grid.best_score_)
# 4.在不同特征子集上运行的分类器的堆叠,不同的1级分类器可以适合训练数据集中的不同特征子集。
from mlxtend.classifier import StackingCVClassifier
from mlxtend.feature_selection import ColumnSelector
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data
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 = StackingCVClassifier(classifiers=[pipe1, pipe2], 
                            meta_classifier=LogisticRegression(),
                            random_state=42)

sclf.fit(X, y)

ROC曲线(过程略)
在这里插入图片描述

参考

http://rasbt.github.io/mlxtend/user_guide/regressor/StackingCVRegressor/
https://machinelearningmastery.com/stacking-ensemble-machine-learning-with-python/

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值