1. 学习知识概要
2. 学习内容
2.1 stacking\blending详解
REF:
- stacking 将若干基学习器获得的预测结果,将预测结果作为新的训练集来训练一个学习器。如下图 假设有五个基学习器,将数据带入五基学习器中得到预测结果,再带入模型六中进行训练预测。但是由于直接由五个基学习器获得结果直接带入模型六中,容易导致过拟合。
因此现在的问题变成如何降低再训练的过拟合性, 这里一般有两种方式:
1. 次级模型尽量选择简单的线性模型
2. 利用第一层训练模型使用交叉验证的方式
- stacking步骤:
- step1 N个基模型训练-k折。
- step2 第二层模型训练-根据第一层k折拼出的结果特征作为训练样本。
- step3 N个基模型在测试集上进行预测-每个基模型,k折对应的k个模型分别预测然后求平均作为该基模型的预测值。
- 第二层模型在测试集上进行预测-基于训练出的第二层模型和N个基模型在测试集上一番操作得到的预测值,进行预测。
- blending 与stacking不同,blending是将预测的值作为新的特征和原特征合并,构成新的特征值,用于预测。为了防止过拟合,将数据分为两部分d1、d2,使用d1的数据作为训练集,d2数据作为测试集。预测得到的数据作为新特征,使用d2的数据作为训练集结合新特征,预测测试集结果。
- blending版本1-单纯的holdout
- step1 基模型训练-在数据集d1上训练N个基模型
- step2 第二层模型训练-将数据集d1的N个预测结果作为新特征,训练得到第二层模型
- step3 基模型预测-使用训练得到的N个基模型在数据集d2上进行预测,即得到了数据集d2上的新特征
- step4 第二层模型预测-基于数据集d2上的新特征和step2得到的第二层模型,预测得到测试集上的预测结果。
- blending版本2-holdout交叉-就是把Stacking流程中的K-Fold CV 改成 HoldOut CV
- step1 N个基模型训练-将数据集d1划分为N份,然后用N种不同的训练集验证集划分方式训练得到。
- step2 第二层模型训练-step1中不同验证集上的预测结果横着拼起来成为N个新特征,入模的label为各个基模型入模样本对应的label进行横向拼接。
- step3 基模型对测试集的预测-N个基模型直接在测试集上进行预测即可。
- step4 第二层模型预测-step3中的预测结果直接横向拼接,作为第二层模型的入模特征进行预测。
- Blending与stacking的不同
- stacking
- stacking中由于两层使用的数据不同,所以可以避免信息泄露的问题。
- 在组队竞赛的过程中,不需要给队友分享自己的随机种子。
- Blending
- 由于blending对将数据划分为两个部分,在最后预测时有部分数据信息将被忽略。
- 同时在使用第二层数据时可能会因为第二层数据较少产生过拟合现象。
- stacking
2.2 代码示例
2.2.1 平均
2.2.2 投票
参考:
2.2.3 Stacking
import warnings
warnings.filterwarnings('ignore')
import itertools
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from sklearn import datasets
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
from sklearn.model_selection import cross_val_score, train_test_split
from mlxtend.plotting import plot_learning_curves
from mlxtend.plotting import plot_decision_regions
# 以python自带的鸢尾花数据集为例
iris = datasets.load_iris()
X, y = iris.data[:, 1:3], iris.target
clf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()
lr = LogisticRegression()
# 基模型:[clf1, clf2, clf3]
# 第二层模型:lr
sclf = StackingClassifier(classifiers=[clf1, clf2, clf3],
meta_classifier=lr)
label = ['KNN', 'Random Forest', 'Naive Bayes', 'Stacking Classifier']
clf_list = [clf1, clf2, clf3, sclf]
fig = plt.figure(figsize=(10,8))
gs = gridspec.GridSpec(2, 2)
grid = itertools.product([0,1],repeat=2)
clf_cv_mean = []
clf_cv_std = []
for clf, label, grd in zip(clf_list, label, grid):
scores = cross_val_score(clf, X, y, cv=5, scoring='accuracy')
print("Accuracy: %.2f (+/- %.2f) [%s]" %(scores.mean(), scores.std(), label))
clf_cv_mean.append(scores.mean())
clf_cv_std.append(scores.std())
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()
Accuracy: 0.91 (+/- 0.07) [KNN] Accuracy: 0.94 (+/- 0.04) [Random Forest] Accuracy: 0.91 (+/- 0.04) [Naive Bayes] Accuracy: 0.94 (+/- 0.04) [Stacking Classifier]
2.2.4 blending
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import roc_auc_score
# 以python自带的鸢尾花数据集为例
data_0 = iris.data
data = data_0[:100,:]
target_0 = iris.target
target = target_0[:100]
#模型融合中基学习器
clfs = [LogisticRegression(),
RandomForestClassifier(),
ExtraTreesClassifier(),
GradientBoostingClassifier()]
#切分一部分数据作为测试集
X, X_predict, y, y_predict = train_test_split(data, target, test_size=0.3, random_state=914)
#切分训练数据集为d1,d2两部分
X_d1, X_d2, y_d1, y_d2 = train_test_split(X, y, test_size=0.5, random_state=914)
dataset_d1 = np.zeros((X_d2.shape[0], len(clfs)))
dataset_d2 = np.zeros((X_predict.shape[0], len(clfs)))
for j, clf in enumerate(clfs):
#依次训练各个单模型
clf.fit(X_d1, y_d1)
y_submission = clf.predict_proba(X_d2)[:, 1]
dataset_d1[:, j] = y_submission
#对于测试集,直接用这k个模型的预测值作为新的特征。
dataset_d2[:, j] = clf.predict_proba(X_predict)[:, 1]
print("val auc Score: %f" % roc_auc_score(y_predict, dataset_d2[:, j]))
#融合使用的模型
clf = GradientBoostingClassifier()
clf.fit(dataset_d1, y_d2)
y_submission = clf.predict_proba(dataset_d2)[:, 1]
print("Val auc Score of Blending: %f" % (roc_auc_score(y_predict, y_submission)))
val auc Score: 1.000000 val auc Score: 1.000000 val auc Score: 1.000000 val auc Score: 1.000000 Val auc Score of Blending: 1.000000