总结下bagging算法和boosting算法:
bagging :基学习器是平行关系,不相互影响,最终将基学习器获得结果:若是分类则投票表决,若是回归则平均
boosting: 基学习器是由依赖关系,前一个基学习器的训练结果“指导”下一个基学习器,当然了不同的boosting算法指导策略是不一样的,然后获得分类或者回归的结果。
stacking算法也是集成算法的一种,说明stacking也是一些基学习器“组成”的强学习器。这个组成策略是什么呢?
我们知道bagging中的策略:若是分类则投票表决(少数服从多数),若是回归则平均
而stacking中的策略:直接采用第二个机器学习模型来将基学习器的结果组合在一起。
这里的基学习器又叫做初级学习器,用于结合的学习器叫做次级学习器或者元学习器(meta-learner)
次学习器用于训练的数据集叫做次级训练集(这个次级训练集是在训练集上用初级学习器得到的)
我们来看下stacking的训练过程:
过程1-3 是训练出来个体学习器,也就是初级学习器。
过程5-9是 使用训练出来的个体学习器来得预测的结果,这个预测的结果当做次级学习器的训练集。
过程11 是用初级学习器预测的结果训练出次级学习器,得到我们最后训练的模型。
如果想要预测一个数据的输出,只需要把这条数据用初级学习器预测,然后将预测后的结果用次级学习器预测便可。
我们列出python的代码,应该更能理解:
构造了个stacking方法
import numpy as np
from sklearn.model_selection import KFold
from sklearn.ensemble import (RandomForestClassifier, AdaBoostClassifier,
GradientBoostingClassifier, ExtraTreesClassifier)
from sklearn.svm import SVC
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
#使用决策树作为我们的次级分类器
from sklearn.tree import DecisionTreeClassifier
def get_stacking(clf, x_train, y_train, x_test, n_folds=10):
"""
这个函数是stacking的核心,使用交叉验证的方法得到次级训练集
x_train, y_train, x_test 的值应该为numpy里面的数组类型 numpy.ndarray .
如果输入为pandas的DataFrame类型则会报错
"""
# print("modle = ",clf)
# print("x_train_dataset:",x_train.shape) #(120,4)
# print("y_train_dataset:",y_train.shape) #(120,)
# print("x_test_dataset:",x_test.shape) #(30,)
train_num, test_num = x_train.shape[0], x_test.shape[0]
second_level_train_set = np.zeros((train_num,))
second_level_test_set = np.zeros((test_num,))
test_nfolds_sets = np.zeros((test_num, n_folds))
kf = KFold(n_splits=n_folds) #实例化
# kf.split(x_train) 引入接口split
for i,(train_index, test_index) in enumerate(kf.split(x_train)):
x_tra, y_tra = x_train[train_index], y_train[train_index]
x_tst, y_tst = x_train[test_index], y_train[test_index]
clf.fit(x_tra, y_tra)
second_level_train_set[test_index] = clf.predict(x_tst)
# print("second_level_train_set:",second_level_train_set.shape)
test_nfolds_sets[:,i] = clf.predict(x_test)
second_level_test_set[:] = test_nfolds_sets.mean(axis=1)
return second_level_train_set, second_level_test_set
#我们这里使用5个分类算法,为了体现stacking的思想,就不加参数了
rf_model = RandomForestClassifier()
adb_model = AdaBoostClassifier()
gdbc_model = GradientBoostingClassifier()
et_model = ExtraTreesClassifier()
svc_model = SVC()
#在这里我们使用train_test_split来人为的制造一些数据
iris = load_iris()
train_x, test_x, train_y, test_y = train_test_split(iris.data, iris.target, test_size=0.2)
train_sets = []
test_sets = []
for clf in [rf_model, adb_model, gdbc_model, et_model, svc_model]:
train_set, test_set = get_stacking(clf, train_x, train_y, test_x)
train_sets.append(train_set)
test_sets.append(test_set)
meta_train = np.concatenate([result_set.reshape(-1,1) for result_set in train_sets], axis=1)
meta_test = np.concatenate([y_test_set.reshape(-1,1) for y_test_set in test_sets], axis=1)
dt_model = DecisionTreeClassifier()
dt_model.fit(meta_train, train_y)
df_predict = dt_model.predict(meta_test)
print(df_predict)
构造stacking类
事实上还可以构造一个stacking的类,它拥有fit和predict方法
from sklearn.model_selection import KFold
from sklearn.base import BaseEstimator, RegressorMixin, TransformerMixin, clone
import numpy as np
#对于分类问题可以使用 ClassifierMixin
class StackingAveragedModels(BaseEstimator, RegressorMixin, TransformerMixin):
def __init__(self, base_models, meta_model, n_folds=5):
self.base_models = base_models
self.meta_model = meta_model
self.n_folds = n_folds
# 我们将原来的模型clone出来,并且进行实现fit功能
def fit(self, X, y):
self.base_models_ = [list() for x in self.base_models]
self.meta_model_ = clone(self.meta_model)
kfold = KFold(n_splits=self.n_folds, shuffle=True, random_state=156)
#对于每个模型,使用交叉验证的方法来训练初级学习器,并且得到次级训练集
out_of_fold_predictions = np.zeros((X.shape[0], len(self.base_models)))
for i, model in enumerate(self.base_models):
for train_index, holdout_index in kfold.split(X, y):
self.base_models_[i].append(instance)
instance = clone(model)
instance.fit(X[train_index], y[train_index])
y_pred = instance.predict(X[holdout_index])
out_of_fold_predictions[holdout_index, i] = y_pred
# 使用次级训练集来训练次级学习器
self.meta_model_.fit(out_of_fold_predictions, y)
return self
#在上面的fit方法当中,我们已经将我们训练出来的初级学习器和次级学习器保存下来了
#predict的时候只需要用这些学习器构造我们的次级预测数据集并且进行预测就可以了
def predict(self, X):
meta_features = np.column_stack([
np.column_stack([model.predict(X) for model in base_models]).mean(axis=1)
for base_models in self.base_models_ ])
return self.meta_model_.predict(meta_features)
Blending:用不相交的数据训练不同的 Base Model,将它们的输出取(加权)平均。实现简单,但对训练数据利用少了。