• 模型融合之Stacking and Blending


    模型融合的基本思想就是集成单个模型以提升整体性能,也就是所说的 Ensemble Model
    常见的模型融合方法有:Bagging、Boosting、Stacking、Blending。

    Bagging:该方法通常考虑的是同质弱学习器,相互独立地并行学习这些弱学习器,并按照某种确定性的平均过程将它们组合起来。单个学习器之间独立学习,学习器之间无依赖,因此可以高效并行学习。模型代表有 随机森林(Random Forest)

    Boosting:该方法通常考虑的也是同质弱学习器。它以一种高度自适应的方法顺序地学习这些弱学习器(每个弱学习器都依赖于前面的学习器),并按照某种确定性的策略将它们组合起来。学习器之间相互依赖,只能在样本上并行,在学习器上无法并行。这类模型有:Adaboost、GBDT、XGBoost等。

    Stacking:该方法通常考虑的是异质弱学习器,并行地学习它们,并通过训练一个「元模型」将它们组合起来,根据不同弱模型的预测结果输出一个最终的预测结果。

    Blending:Blending与Stacking大致相同,主要区别在于训练集不是通过K-Fold的CV策略来获得预测值从而生成第二阶段模型的特征,而是建立一个Holdout集。简单来说,Blending直接用不相交的数据集用于不同层的训练。
    以两层的Blending为例,训练集划分为两部分(d1,d2),测试集为test。
    第一层:用d1训练多个模型,将其对d2和test的预测结果作为第二层的New Features。
    第二层:用d2的New Features和标签训练新的分类器,然后把test的New Features输入作为最终的测试集,对test预测出的结果就是最终的模型融合的值。
    缺点是,d1未参与第二层的模型训练,每一层的训练数据量较上一层都有所减少,后续的模型看到的训练数据越来越少。

    下面结合模型架构和代码重点解释一下 Stacking和Blending方法。

    Stacking

    在这里插入图片描述

    from sklearn import datasets
    from sklearn.ensemble import RandomForestClassifier, ExtraTreesClassifier, GradientBoostingClassifier
    from sklearn.model_selection import train_test_split
    from sklearn.model_selection import StratifiedKFold
    import numpy as np
    from sklearn.metrics import roc_auc_score
    from sklearn.datasets.samples_generator import make_blobs
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    # 创建训练的数据集
    data, target = make_blobs(n_samples=50000, centers=2, random_state=0, cluster_std=0.60)
    
    • 1
    • 2
    # 模型融合中使用到的各个单模型
    clfs = [RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
            RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'),
            ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
            ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'),
            GradientBoostingClassifier(learning_rate=0.05, subsample=0.5, max_depth=6, n_estimators=5)]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    # 切分一部分数据作为测试集
    X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.33, random_state=2017)
    dataset_blend_train = np.zeros((X_train.shape[0], len(clfs)))
    dataset_blend_test = np.zeros((X_test.shape[0], len(clfs)))
    
    # 定义交叉验证折数
    # 4折stacking
    n_folds = 4
    
    skf = StratifiedKFold(n_splits=n_folds)
    train_val = list(skf.split(X_train, y_train))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    # 第一层将原始X作为特征
    for j, clf in enumerate(clfs):
        dataset_blend_test_j = np.zeros((X_test.shape[0], n_folds))
        for i, (train, val) in enumerate(train_val):
            # 使用第i个部分作为预测,剩余的部分来训练模型,获得其预测的输出作为第i部分的新特征。
            X_tra, y_tra, X_val, y_val = X_train[train], y_train[train], X_train[val], y_train[val]
            clf.fit(X_tra, y_tra)
            y_submission = clf.predict_proba(X_val)[:, 1]
            dataset_blend_train[val, j] = y_submission
            dataset_blend_test_j[:, i] = clf.predict_proba(X_test)[:, 1]
        # 对于测试集,直接用这k个模型的预测值均值作为新的特征。
        dataset_blend_test[:, j] = dataset_blend_test_j.mean(1)
        print("Model Name: {0:<30},  Val auc score: {1:.5f}".format(clf.__class__.__name__, roc_auc_score(y_test, dataset_blend_test[:, j])))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    打印结果:
    Model Name: RandomForestClassifier , Val auc score: 0.99956
    Model Name: RandomForestClassifier , Val auc score: 0.99963
    Model Name: ExtraTreesClassifier , Val auc score: 0.99980
    Model Name: ExtraTreesClassifier , Val auc score: 0.99975
    Model Name: GradientBoostingClassifier , Val auc score: 0.99974

    # 第二层将上一层预测的结果作为特征
    clf = GradientBoostingClassifier(learning_rate=0.02, subsample=0.5, max_depth=6, n_estimators=30)
    clf.fit(dataset_blend_train, y)
    y_submission = clf.predict_proba(dataset_blend_test)[:, 1]
    
    
    print("Linear stretch of predictions to [0,1]")
    y_submission = (y_submission - y_submission.min()) / (y_submission.max() - y_submission.min())
    print("stack result")
    print("val auc Score: %f" % (roc_auc_score(y_predict, y_submission)))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    Linear stretch of predictions to [0,1]
    stack result
    val auc Score: 0.999617
    
    • 1
    • 2
    • 3

    Blending

    # 切分训练数据集为d1,d2两部分
    X_d1, X_d2, y_d1, y_d2 = train_test_split(X_train, y_train, test_size=0.5, random_state=2017)
    dataset_d1 = np.zeros((X_d2.shape[0], len(clfs)))
    dataset_d2 = np.zeros((X_test.shape[0], len(clfs)))
    
    • 1
    • 2
    • 3
    • 4
    # 第一层
    for j, clf in enumerate(clfs):
        '''依次训练各个单模型'''
        # print(j, clf)
        '''使用第1个部分作为预测,第2部分来训练模型,获得其预测的输出作为第2部分的新特征。'''
        # X_train, y_train, X_test, y_test = X[train], y[train], X[test], y[test]
        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_test)[:, 1]
        print("Model Name: {0:<30},  Val auc score: {1:.5f}".format(clf.__class__.__name__, 
                                                                    roc_auc_score(y_test, dataset_d2[:, j])))
    # 第二层
    
    '''融合使用的模型'''
    # clf = LogisticRegression()
    clf = GradientBoostingClassifier(learning_rate=0.02, subsample=0.5, max_depth=6, n_estimators=30)
    clf.fit(dataset_d1, y_d2)
    y_submission = clf.predict_proba(dataset_d2)[:, 1]
    
    print('----------')
    print("Linear stretch of predictions to [0,1]")
    y_submission = (y_submission - y_submission.min()) / (y_submission.max() - y_submission.min())
    print("blend result")
    print("val auc Score: %f" % (roc_auc_score(y_predict, y_submission)))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    打印结果:
    Model Name: RandomForestClassifier , Val auc score: 0.99903
    Model Name: RandomForestClassifier , Val auc score: 0.99927
    Model Name: ExtraTreesClassifier , Val auc score: 0.99944
    Model Name: ExtraTreesClassifier , Val auc score: 0.99938
    Model Name: GradientBoostingClassifier , Val auc score: 0.99871
    ----------
    Linear stretch of predictions to [0,1]
    blend result
    val auc Score: 0.999272

  • 相关阅读:
    【面试算法——动态规划 21】不同的子序列(hard)&& 通配符匹配(hard)
    Unity中程序集dll
    Android 10.0 app全屏系统属性控制上滑是否显示虚拟导航栏和状态栏
    【JVM笔记】同步控制字节码指令
    Java 序列化和反序列化为什么要实现 Serializable 接口?
    MongoDB脑裂恢复
    力扣精选算法100道——提莫攻击(模拟专题)
    给 Angular 服务器端渲染应用设置一个渲染超时时间
    微信小程序集成腾讯im,会话列表数据过多(长列表),卡顿问题的解决
    置业小技能:按揭相关事项
  • 原文地址:https://blog.csdn.net/qq_32275289/article/details/126727328