[机器学习] 集成学习 stacking

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

栈泛化就是集成学习(Ensemble learning)中Aggregation方法进一步泛化的结果, 是通过Meta-Learner来取代Bagging和Boosting的Voting/Averaging来综合降低Bias和Variance的方法。
譬如: Voting可以通过kNN来实现, weighted voting可以通过softmax(Logistic Regression), 而Averaging可以通过线性回归来实现。
同源集成经典方法中的Voting和Averaging。

1.平均法

2.投票法

3.学习法 stacking

Stacked Generalization (SG),也叫堆栈泛化的方法,属于异源集成(heterogenous ensembles)的典型代表

① 将训练集分为3部分,分别用于让3个基分类器(Base-leaner)进行学习和拟合
② 将3个基分类器预测得到的结果作为下一层分类器(Meta-learner)的输入
③ 将下一层分类器得到的结果作为最终的预测结果
这个模型的特点就是通过使用第一阶段(level 0)的预测作为下一层预测的特征,比起相互独立的预测模型能够有更强的非线性表述能力,降低泛化误差。它的目标是同时降低机器学习模型的Bias-Variance。

对于每一轮的 5-fold,Model 1都要做满5次的训练和预测。
Titanic 栗子:
Train Data有890行。(请对应图中的上层部分)

每1次的fold,都会生成 713行 小train, 178行 小test。我们用Model 1来训练 713行的小train,然后预测 178行 小test。预测的结果是长度为 178 的预测值。
这样的动作走5次! 长度为178 的预测值 X 5 = 890 预测值,刚好和Train data长度吻合。这个890预测值是Model 1产生的,我们先存着,因为,一会让它将是第二层模型的训练来源。

重点:这一步产生的预测值我们可以转成 890 X 1 (890 行,1列),记作 P1 (大写P)

接着说 Test Data 有 418 行。(请对应图中的下层部分,对对对,绿绿的那些框框)

每1次的fold,713行 小train训练出来的Model 1要去预测我们全部的Test Data(全部!因为Test Data没有加入5-fold,所以每次都是全部!)。此时,Model 1的预测结果是长度为418的预测值。

这样的动作走5次!我们可以得到一个 5 X 418 的预测值矩阵。然后我们根据行来就平均值,最后得到一个 1 X 418 的平均预测值。

重点:这一步产生的预测值我们可以转成 418 X 1 (418行,1列),记作 p1 (小写p)

走到这里,你的第一层的Model 1完成了它的使命。
第一层还会有其他Model的,比如Model 2,同样的走一遍, 我们有可以得到 890 X 1 (P2) 和 418 X 1 (p2) 列预测值。
这样吧,假设你第一层有3个模型,这样你就会得到:
来自5-fold的预测值矩阵 890 X 3,(P1,P2, P3) 和 来自Test Data预测值矩阵 418 X 3, (p1, p2, p3)。


到第二层了…

来自5-fold的预测值矩阵 890 X 3 作为你的Train Data,训练第二层的模型
来自Test Data预测值矩阵 418 X 3 就是你的Test Data,用训练好的模型来预测他们吧。


class Ensemble(object):
    def __init__(self, n_folds, stacker, base_models):
        self.n_folds = n_folds
        self.stacker = stacker
        self.base_models = base_models

    def fit_predict(self, X, y, T):
        X = np.array(X)
        y = np.array(y)
        T = np.array(T)

        folds = list(KFold(len(y), n_folds=self.n_folds, shuffle=True, random_state=2016))

        S_train = np.zeros((X.shape[0], len(self.base_models)))
        S_test = np.zeros((T.shape[0], len(self.base_models)))

        for i, clf in enumerate(self.base_models):
            S_test_i = np.zeros((T.shape[0], len(folds)))

            for j, (train_idx, test_idx) in enumerate(folds):
                X_train = X[train_idx]
                y_train = y[train_idx]
                X_holdout = X[test_idx]
                # y_holdout = y[test_idx]
                clf.fit(X_train, y_train)
                y_pred = clf.predict(X_holdout)[:]
                S_train[test_idx, i] = y_pred
                S_test_i[:, j] = clf.predict(T)[:]

            S_test[:, i] = S_test_i.mean(1)

        self.stacker.fit(S_train, y)
        y_pred = self.stacker.predict(S_test)[:]
        return y_pred

参考

模型融合方法概述
Kaggle机器学习之模型融合(stacking)心得
今我来思,堆栈泛化
如何在 kaggle中首战进入10%
https://blog.csdn.net/Julialove102123/article/details/78475774
https://blog.csdn.net/savinger/article/details/52862004
https://blog.csdn.net/g11d111/article/details/80215381

猜你喜欢

转载自blog.csdn.net/u013608336/article/details/82745804