精华内容
下载资源
问答
  • 模型融合

    万次阅读 2016-08-25 21:55:52
    本文包括常见的模型融合方法、代码链接、进阶的思路。1.线性加权融合方法从算法的角度来看,则最常用的是采用加权型的混合推荐技术,即将来自不同推荐算法生成的候选结果及结果的分数,进一步进行组合(Ensemble)...

    本文包括常见的模型融合方法、代码链接、进阶的思路。

    1.线性加权融合方法

    从算法的角度来看,则最常用的是采用加权型的混合推荐技术,即将来自不同推荐算法生成的候选结果及结果的分数,进一步进行组合(Ensemble)加权,生成最终的推荐排序结果。

    具体来看,比较原始的加权型的方法是根据推荐效果,固定赋予各个子算法输出结果的权重,然后得到最终结果。很显然这种方法无法灵活处理不同的上下文场景,因为不同的算法的结果,可能在不同的场景下质量有高有低,固定加权系统无法各取所长。所以更好的思路是设置训练样本,然后比较用户对推荐结果的评价、与系统的预测是否相符,根据训练得到的结果生成加权的模型,动态的调整权重。


    加权混合技术能明显提高推荐精度

    加权混合的模型有很多,除了简单的线性模型外,常用的有回归模型(Logistic Regression)、RBM(Restricted Boltzmann Machines)、GBDT(Gradient Boosted Decision Trees),这三种混合模型在推荐算法竞赛中大放异彩,在2009年结束的Netflix百万美元推荐竞赛中,优胜队伍将充分运用和多种加权混合模型的优势,组合后的算法推荐精度非常高。获胜队的Yehuda Koren在论文The BellKor Solution to the Netflix Grand Prize中对此有非常详细的介绍。另外值得一提的是台湾大学推荐团队,他们通过混合甚至二次混合的方式(如上图),将众多单独推荐算法的结果进行最合理的加权组合,在最近几届的KDD Cup数据挖掘竞赛中所向披靡,经常取得极为优异的推荐效果。

    实际coding,加权可以参数可以通过线下测试集获得(需要线下与线上数据分布类似)

    2.交叉融合法

    交叉融合常被称为Blending方法,其思路是在推荐结果中,穿插不同推荐模型的结果,以确保结果的多样性。

    这种方式将不同算法的结果组合在一起推荐给用户

    交叉融合法的思路是“各花入各眼”,不同算法的结果着眼点不同,能满足不同用户的需求,直接穿插在一起进行展示。这种融合方式适用于同时能够展示较多条结果的推荐场景,并且往往用于算法间区别较大,如分别基于用户长期兴趣和短期兴趣计算获得的结果。

    使用blending进行ensemble代码
    https://github.com/emanuele/kaggle_pbr/blob/master/blend.py#L57

    3.瀑布融合法

    瀑布型(Waterfall Model)融合方法采用了将多个模型串联的方法。每个推荐算法被视为一个过滤器,通过将不同粒度的过滤器前后衔接的方法来进行:

    在瀑布型混合技术中,前一个推荐方法过滤的结果,将作为后一个推荐方法的候选集合输入,层层递进,候选结果在此过程中会被逐步遴选,最终得到一个量少质高的结果集合。这样设计通常用于存在大量候选集合的推荐场景上。

    设计瀑布型混合系统中,通常会将运算速度快、区分度低的算法排在前列,逐步过渡为重量级的算法,让宝贵的运算资源集中在少量较高候选结果的运算上。在面对候选推荐对象(Item)数量庞大,而可曝光的推荐结果较少,要求精度较高、且运算时间有限的场景下,往往非常适用。

    笔者看过天池-移动推荐大赛的最终解决方案,在样本选择时,top 5团队均选择历史用过交互的商品,而非商品全集。这也是一种Filter。

    4.多而不同之融合

    不同是指参数、特征、样本不同,下面以特征不同为例。

    不同的原始数据质量,对推荐计算的结果有很大的影响。以用户兴趣模型为例,我们既可以从用户的实际购买行为中,挖掘出用户的“显式”兴趣,又可以用用户的点击行为中,挖掘用户“隐式”兴趣;另外从用户分类、人口统计学分析中,也可以推测用户偏好;如果有用户的社交网络,那么也可以了解周围用户对该用户兴趣的影响。

    所以通过使用不同的数据来源,抽取不同的特征,输入到推荐模型中进行训练,然后将结果合并。这种思路能解决现实中经常遇到的数据缺失的问题,因为并非所有用户都有齐全的各类数据,例如有些用户就缺少交易信息,有些则没有社交关系数据等。通过特征融合的方法能确保模型不挑食,扩大适用面。

    5.预测融合法

    推荐算法也可以被视为一种“预测算法”,即我们为每个用户来预测他接下来最有可能喜欢的商品。而预测融合法的思想是,我们可以对每个预测算法再进行一次预测,即不同的算法的预测结果,我们可以训练第二层的预测算法去再次进行预测,并生成最终的预测结果。

    如下图所示,我们把各个推荐算法的预测结果作为特征,将用户对商品的反馈数据作为训练样本,形成了第二层预测模型的训练集合,具体流程如下

    图中的二层预测模型可以使用常用的分类算法,如SVM、随机森林、最大熵等,但达观实践中,融合效果较好的是GBDT(Gradient Boosting Decision Tree)方法。

    6.加性融合

    一个很赞的idea

    非线性的树模型Additive Groves(AG)是一个加性模型,由很多个Grove组成,不同的Grove之间进行bagging得出最后的预测结果,由此可以减小过拟合的影响。

    每一个Grove有多棵树组成,在训练时每棵树的拟合目标为真实值与其他树预测结果之和之间的残差。当达到给定数目的树时,重新训练的树会逐棵替代以前的树。经过多次迭代后,达到收敛。

    最后,强势安利一波,Kaggle关于ensemble的文档

    http://mlwave.com/kaggle-ensembling-guide/

    参考文献
    (1)http://blog.sina.com.cn/s/blog_5357c0af0102uxof.html
    (2)http://www.csdn.net/article/2015-01-30/2823783

    展开全文
  • 模型融合

    千次阅读 2019-11-28 10:57:42
    机器学习模型和深度学习模型的...因此通过一些科学的方法对优秀的模型进行融合,来突破单个模型对未知问题的泛化能力的瓶颈,并综合各个模型的优点得到同一个模型的最优解决方法,这就是多模型融合。 1 多模型融合入...

    机器学习模型和深度学习模型的泛化能力是评估模型好坏的一个非常重要的指标,但在使用单一模型处理某个问题时很容易遇到模型泛化瓶颈。此外,建立一个模型后,这个模型可能在解决某个问题的能力上比较出色,在解决其他问题时,结果却不尽如人意。因此通过一些科学的方法对优秀的模型进行融合,来突破单个模型对未知问题的泛化能力的瓶颈,并综合各个模型的优点得到同一个模型的最优解决方法,这就是多模型融合。

    1 多模型融合入门

    在多模型融合过程中一般会遇到两个问题,第一个问题是训练复杂的神经网络非常耗时,因为优秀的模型一般都是深度神经网络模型,其层次较深,参数较多。对多个深度神经网络的模型融合进行参数训练时,会比单一的深度神经网络模型更加耗时。
    一般通过选择结构较简单、网络层数较少的神经网络模型参与到多模型融合中;当使用了深度神经网络模型进行多模型融合时,一般通过迁移学习方法来辅助模型的训练,减少训练耗时。
    第二个问题时进行多模型融合时,融合方法的类型选择让人头疼。选择不同的模型融合方法解决某些问题时,其结果的表现不同,此外是针对模型的过程进行融合还是针对各个模型输出的结果进行融合,也值得考虑。
    此处以结果融合方法为例进行简单介绍,结果融合方法主要有结果多数表决、结果直接平均和结果加权平均三种主要的类型。
    在结果融合法有一个比较通用的理论,融合的各个模型相关度越低,模型融合的效果会更好,也就是说各个模型输出结果的差异性越高(比如神经网络和树模型),多模型融合效果就越好。

    1.1 结果多数表决

    结果多数表决类似于投票表决,一般选取的模型融合个数为奇数,否则有可能出现无法判断的情况。

    1.2 结果直接平均

    结果直接平均追求的是融合各个模型的平均水平,不强调个别模型的突出优势,可弥补个别模型的明显劣势。

    1.3 结果加权平均

    可将结果加权平均看做直接平均的改进版本,在结果加权平均方法中会新增一个权重参数,这个权重参数用于控制各个模型对融合结果的影响程度。不同的权重组合对最终的融合模型的结果影响较大,一般需尝试不同的权重值进行组合,以达到最优的多模型融合解决方案。

    展开全文
  • stacking模型融合

    千次阅读 2020-04-04 20:16:00
    模型融合 模型融合的方法 简单加权融合: 回归(分类概率):算术平均融合(Arithmetic mean),几何平均融合(Geometric mean); 分类:投票(Voting) 综合:排序融合(Rank averaging),log融合 stacking/...

    模型融合

    模型融合的方法

    1. 简单加权融合:

      • 回归(分类概率):算术平均融合(Arithmetic mean),几何平均融合(Geometric mean);
      • 分类:投票(Voting)
      • 综合:排序融合(Rank averaging),log融合
    2. stacking/blending:

      • 构建多层模型,并利用预测结果再拟合预测。
    3. boosting/bagging(在xgboost,Adaboost,GBDT中已经用到):

      • 多树的提升方法

    stacking相关理论介绍

    1. 什么是 stacking

    简单来说 stacking 就是当用初始训练数据学习出若干个基学习器后,将这几个学习器的预测结果作为新的训练集,来学习一个新的学习器。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wHQRdyI9-1586002387196)(stacking流程图.png)]

    将个体学习器结合在一起的时候使用的方法叫做结合策略。对于分类问题,我们可以使用投票法来选择输出最多的类。对于回归问题,我们可以将分类器输出的结果求平均值。

    上面说的投票法和平均法都是很有效的结合策略,还有一种结合策略是使用另外一个机器学习算法来将个体机器学习器的结果结合在一起,这个方法就是Stacking。

    在stacking方法中,我们把个体学习器叫做初级学习器,用于结合的学习器叫做次级学习器或元学习器(meta-learner),次级学习器用于训练的数据叫做次级训练集。次级训练集是在训练集上用初级学习器得到的。

    1. stacking的工作方式
      在这里插入图片描述

    引自西瓜书(机器学习)

    • 过程1-3 是训练出来个体学习器,也就是初级学习器。
    • 过程5-9是 使用训练出来的个体学习器来得预测的结果,这个预测的结果当做次级学习器的训练集。
    • 过程11 是用初级学习器预测的结果训练出次级学习器,得到我们最后训练的模型。

    3)Stacking的方法讲解

    首先,我们先从一种“不那么正确”但是容易懂的Stacking方法讲起。

    Stacking模型本质上是一种分层的结构,这里简单起见,只分析二级Stacking.假设我们有2个基模型 Model1_1、Model1_2 和 一个次级模型Model2

    Step 1. 基模型 Model1_1,对训练集train训练,然后用于预测 train 和 test 的标签列,分别是P1,T1

    在这里插入图片描述

    训练后的模型 Model1_1 分别在 train 和 test 上预测,得到预测标签分别是P1,T1

    Step 2. 基模型 Model1_2 ,对训练集train训练,然后用于预测train和test的标签列,分别是P2,T2

    在这里插入图片描述

    训练后的模型 Model1_2 分别在 train 和 test 上预测,得到预测标签分别是P2,T2

    Step 3. 分别把P1,P2以及T1,T2合并,得到一个新的训练集和测试集train2,test2.

    在这里插入图片描述

    再用 次级模型 Model2 以真实训练集标签为标签训练,以train2为特征进行训练,预测test2,得到最终的测试集预测的标签列 Y P r e Y_{Pre} YPre

    这就是我们两层堆叠的一种基本的原始思路想法。在不同模型预测的结果基础上再加一层模型,进行再训练,从而得到模型最终的预测。

    Stacking本质上就是这么直接的思路,但是直接这样有时对于如果训练集和测试集分布不那么一致的情况下是有一点问题的,其问题在于用初始模型训练的标签再利用真实标签进行再训练,毫无疑问会导致一定的模型过拟合训练集,这样或许模型在测试集上的泛化能力或者说效果会有一定的下降,因此现在的问题变成了如何降低再训练的过拟合性,这里我们一般有两种方法。

      1. 次级模型尽量选择简单的线性模型
      1. 利用K折交叉验证

    K-折交叉验证:
    训练:
    在这里插入图片描述
    预测:
    在这里插入图片描述

    代码示例

    回归\分类概率-融合:

    1)简单加权平均,结果直接融合

    ## 生成一些简单的样本数据,test_prei 代表第i个模型的预测值
    test_pre1 = [1.2, 3.2, 2.1, 6.2]
    test_pre2 = [0.9, 3.1, 2.0, 5.9]
    test_pre3 = [1.1, 2.9, 2.2, 6.0]
    
    # y_test_true 代表第模型的真实值
    y_test_true = [1, 3, 2, 6] 
    
    import numpy as np
    import pandas as pd
    
    ## 定义结果的加权平均函数
    def Weighted_method(test_pre1,test_pre2,test_pre3,w=[1/3,1/3,1/3]):
        Weighted_result = w[0]*pd.Series(test_pre1)+w[1]*pd.Series(test_pre2)+w[2]*pd.Series(test_pre3)
        return Weighted_result
    
    from sklearn import metrics
    # 各模型的预测结果计算MAE
    print('Pred1 MAE:',metrics.mean_absolute_error(y_test_true, test_pre1))
    print('Pred2 MAE:',metrics.mean_absolute_error(y_test_true, test_pre2))
    print('Pred3 MAE:',metrics.mean_absolute_error(y_test_true, test_pre3))
    
    Pred1 MAE: 0.1750000000000001
    Pred2 MAE: 0.07499999999999993
    Pred3 MAE: 0.10000000000000009
    
    ## 根据加权计算MAE
    w = [0.3,0.4,0.3] # 定义比重权值
    Weighted_pre = Weighted_method(test_pre1,test_pre2,test_pre3,w)
    print('Weighted_pre MAE:',metrics.mean_absolute_error(y_test_true, Weighted_pre))
    
    Weighted_pre MAE: 0.05750000000000027
    

    可以发现加权结果相对于之前的结果是有提升的,这种我们称其为简单的加权平均。
    还有一些特殊的形式,比如mean平均,median平均

    ## 定义结果的加权平均函数
    def Mean_method(test_pre1,test_pre2,test_pre3):
        Mean_result = pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).mean(axis=1)
        return Mean_result
    Mean_pre = Mean_method(test_pre1,test_pre2,test_pre3)
    print('Mean_pre MAE:',metrics.mean_absolute_error(y_test_true, Mean_pre))
    
    Mean_pre MAE: 0.06666666666666693
    
    ## 定义结果的加权平均函数
    def Median_method(test_pre1,test_pre2,test_pre3):
        Median_result = pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).median(axis=1)
        return Median_result
    Median_pre = Median_method(test_pre1,test_pre2,test_pre3)
    print('Median_pre MAE:',metrics.mean_absolute_error(y_test_true, Median_pre))
    
    Median_pre MAE: 0.07500000000000007
    

    2) Stacking融合(回归):

    from sklearn import linear_model
    
    def Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,test_pre1,test_pre2,test_pre3,model_L2= linear_model.LinearRegression()):
        model_L2.fit(pd.concat([pd.Series(train_reg1),pd.Series(train_reg2),pd.Series(train_reg3)],axis=1).values,y_train_true)
        Stacking_result = model_L2.predict(pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).values)
        return Stacking_result
    
    ## 生成一些简单的样本数据,test_prei 代表第i个模型的预测值
    train_reg1 = [3.2, 8.2, 9.1, 5.2]
    train_reg2 = [2.9, 8.1, 9.0, 4.9]
    train_reg3 = [3.1, 7.9, 9.2, 5.0]
    # y_test_true 代表第模型的真实值
    y_train_true = [3, 8, 9, 5] 
    
    test_pre1 = [1.2, 3.2, 2.1, 6.2]
    test_pre2 = [0.9, 3.1, 2.0, 5.9]
    test_pre3 = [1.1, 2.9, 2.2, 6.0]
    
    # y_test_true 代表第模型的真实值
    y_test_true = [1, 3, 2, 6] 
    
    model_L2= linear_model.LinearRegression()
    Stacking_pre = Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,
                                   test_pre1,test_pre2,test_pre3,model_L2)
    print('Stacking_pre MAE:',metrics.mean_absolute_error(y_test_true, Stacking_pre))
    
    Stacking_pre MAE: 0.04213483146067476
    

    可以发现模型结果相对于之前有进一步的提升,这是我们需要注意的一点是,对于第二层Stacking的模型不宜选取的过于复杂,这样会导致模型在训练集上过拟合,从而使得在测试集上并不能达到很好的效果。

    分类模型融合:

    对于分类,同样的可以使用融合方法,比如简单投票,Stacking…

    from sklearn.datasets import make_blobs
    from sklearn import datasets
    from sklearn.tree import DecisionTreeClassifier
    import numpy as np
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.ensemble import VotingClassifier
    from xgboost import XGBClassifier
    from sklearn.linear_model import LogisticRegression
    from sklearn.svm import SVC
    from sklearn.model_selection import train_test_split
    from sklearn.datasets import make_moons
    from sklearn.metrics import accuracy_score,roc_auc_score
    from sklearn.model_selection import cross_val_score
    from sklearn.model_selection import StratifiedKFold
    

    1)Voting投票机制:

    Voting即投票机制,分为软投票和硬投票两种,其原理采用少数服从多数的思想。

    iris = datasets.load_iris()
    
    x=iris.data
    y=iris.target
    x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3)
    
    clf1 = XGBClassifier(learning_rate=0.1, n_estimators=150, max_depth=3, min_child_weight=2, subsample=0.7,
                         colsample_bytree=0.6, objective='binary:logistic')
    clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4,
                                  min_samples_leaf=63,oob_score=True)
    clf3 = SVC(C=0.1, gamma='auto')
    
    # 硬投票
    eclf = VotingClassifier(estimators=[('xgb', clf1), ('rf', clf2), ('svc', clf3)], voting='hard')
    for clf, label in zip([clf1, clf2, clf3, eclf], ['XGBBoosting', 'Random Forest', 'SVM', 'Ensemble']):
        scores = cross_val_score(clf, x, y, cv=5, scoring='accuracy')
        print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))
    
    Accuracy: 0.96 (+/- 0.02) [XGBBoosting]
    Accuracy: 0.33 (+/- 0.00) [Random Forest]
    Accuracy: 0.95 (+/- 0.03) [SVM]
    Accuracy: 0.95 (+/- 0.03) [Ensemble]
    
    '''
    软投票:和硬投票原理相同,增加了设置权重的功能,可以为不同模型设置不同权重,进而区别模型不同的重要度。
    '''
    x=iris.data
    y=iris.target
    x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3)
    
    clf1 = XGBClassifier(learning_rate=0.1, n_estimators=150, max_depth=3, min_child_weight=2, subsample=0.8,
                         colsample_bytree=0.8, objective='binary:logistic')
    clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4,
                                  min_samples_leaf=63,oob_score=True)
    clf3 = SVC(C=0.1, probability=True, gamma='auto')
    
    # 软投票
    eclf = VotingClassifier(estimators=[('xgb', clf1), ('rf', clf2), ('svc', clf3)], voting='soft', weights=[4, 1, 1])
    clf1.fit(x_train, y_train)
    
    for clf, label in zip([clf1, clf2, clf3, eclf], ['XGBBoosting', 'Random Forest', 'SVM', 'Ensemble']):
        scores = cross_val_score(clf, x, y, cv=5, scoring='accuracy')
        print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))
    
    Accuracy: 0.96 (+/- 0.02) [XGBBoosting]
    Accuracy: 0.33 (+/- 0.00) [Random Forest]
    Accuracy: 0.95 (+/- 0.03) [SVM]
    Accuracy: 0.96 (+/- 0.02) [Ensemble]
    

    2)分类的Stacking\Blending融合:

    stacking是一种分层模型集成框架。

    以两层为例,第一层由多个基学习器组成,其输入为原始训练集,第二层的模型则是以第一层基学习器的输出作为训练集进行再训练,从而得到完整的stacking模型, stacking两层模型都使用了全部的训练数据。

    '''
    5-Fold Stacking
    '''
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.ensemble import ExtraTreesClassifier,GradientBoostingClassifier
    import pandas as pd
    #创建训练的数据集
    data_0 = iris.data
    data = data_0[:100,:]
    
    target_0 = iris.target
    target = target_0[:100]
    
    #模型融合中使用到的各个单模型
    clfs = [LogisticRegression(solver='lbfgs'),
            RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
            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)]
     
    #切分一部分数据作为测试集
    X, X_predict, y, y_predict = train_test_split(data, target, test_size=0.3, random_state=0)
    
    dataset_blend_train = np.zeros((X.shape[0], len(clfs)))
    dataset_blend_test = np.zeros((X_predict.shape[0], len(clfs)))
    
    #5折stacking
    n_splits = 5
    skf = StratifiedKFold(n_splits)
    skf = skf.split(X, y)
    
    for j, clf in enumerate(clfs):
        #依次训练各个单模型
        dataset_blend_test_j = np.zeros((X_predict.shape[0], len(clfs)))
        for i, (train, test) in enumerate(skf):
            #5-Fold交叉训练,使用第i个部分作为预测,剩余的部分来训练模型,获得其预测的输出作为第i部分的新特征。
            X_train, y_train, X_test, y_test = X[train], y[train], X[test], y[test]
            clf.fit(X_train, y_train)
            y_submission = clf.predict_proba(X_test)[:, 1]
            dataset_blend_train[test, j] = y_submission
            dataset_blend_test_j[:, i] = clf.predict_proba(X_predict)[:, 1]
        #对于测试集,直接用这交叉验证训练的模型的预测值均值作为新的特征。
        dataset_blend_test[:, j] = dataset_blend_test_j.mean(1)
        print("val auc Score: %f" % roc_auc_score(y_predict, dataset_blend_test[:, j]))
    
    clf = LogisticRegression(solver='lbfgs')
    clf.fit(dataset_blend_train, y)
    y_submission = clf.predict_proba(dataset_blend_test)[:, 1]
    
    print("Val auc Score of Stacking: %f" % (roc_auc_score(y_predict, y_submission)))
    
    
    val auc Score: 1.000000
    val auc Score: 0.500000
    val auc Score: 0.500000
    val auc Score: 0.500000
    val auc Score: 0.500000
    Val auc Score of Stacking: 1.000000
    

    Blending,其实和Stacking是一种类似的多层模型融合的形式

    其主要思路是把原始的训练集先分成两部分,比如70%的数据作为新的训练集,剩下30%的数据作为测试集。

    在第一层,我们在这70%的数据上训练多个模型,然后去预测那30%数据的label,同时也预测test集的label。

    在第二层,我们就直接用这30%数据在第一层预测的结果做为新特征继续训练,然后用test集第一层预测的label做特征,用第二层训练的模型做进一步预测

    其优点在于:

    • 1.比stacking简单(因为不用进行k次的交叉验证来获得stacker feature)
    • 2.避开了一个信息泄露问题:generlizers和stacker使用了不一样的数据集

    缺点在于:

    • 1.使用了很少的数据(第二阶段的blender只使用training set10%的量)
    • 2.blender可能会过拟合
    • 3.stacking使用多次的交叉验证会比较稳健
      ‘’’
    '''
    Blending
    '''
     
    #创建训练的数据集
    #创建训练的数据集
    data_0 = iris.data
    data = data_0[:100,:]
    
    target_0 = iris.target
    target = target_0[:100]
     
    #模型融合中使用到的各个单模型
    clfs = [LogisticRegression(solver='lbfgs'),
            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)]
     
    #切分一部分数据作为测试集
    X, X_predict, y, y_predict = train_test_split(data, target, test_size=0.3, random_state=2020)
    
    #切分训练数据集为d1,d2两部分
    X_d1, X_d2, y_d1, y_d2 = train_test_split(X, y, test_size=0.5, random_state=2020)
    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(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("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: 1.000000
    Val auc Score of Blending: 1.000000
    

    3)分类的Stacking融合(利用mlxtend):

    
    
    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
    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()
    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=3, 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.01) [KNN]
    Accuracy: 0.93 (+/- 0.05) [Random Forest]
    Accuracy: 0.92 (+/- 0.03) [Naive Bayes]
    Accuracy: 0.95 (+/- 0.03) [Stacking Classifier]
    

    在这里插入图片描述

    可以发现 基模型 用 ‘KNN’, ‘Random Forest’, ‘Naive Bayes’ 然后再这基础上 次级模型加一个 ‘LogisticRegression’,模型测试效果有着很好的提升。

    一些其它方法:

    将特征放进模型中预测,并将预测结果变换并作为新的特征加入原有特征中再经过模型预测结果 (Stacking变化)

    (可以反复预测多次将结果加入最后的特征中)

    def Ensemble_add_feature(train,test,target,clfs):
        
        # n_flods = 5
        # skf = list(StratifiedKFold(y, n_folds=n_flods))
    
        train_ = np.zeros((train.shape[0],len(clfs*2)))
        test_ = np.zeros((test.shape[0],len(clfs*2)))
    
        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(train,target)
            y_train = clf.predict(train)
            y_test = clf.predict(test)
    
            ## 新特征生成
            train_[:,j*2] = y_train**2
            test_[:,j*2] = y_test**2
            train_[:, j+1] = np.exp(y_train)
            test_[:, j+1] = np.exp(y_test)
            # print("val auc Score: %f" % r2_score(y_predict, dataset_d2[:, j]))
            print('Method ',j)
        
        train_ = pd.DataFrame(train_)
        test_ = pd.DataFrame(test_)
        return train_,test_
    
    
    from sklearn.model_selection import cross_val_score, train_test_split
    from sklearn.linear_model import LogisticRegression
    clf = LogisticRegression()
    
    data_0 = iris.data
    data = data_0[:100,:]
    
    target_0 = iris.target
    target = target_0[:100]
    
    x_train,x_test,y_train,y_test=train_test_split(data,target,test_size=0.3)
    x_train = pd.DataFrame(x_train) ; x_test = pd.DataFrame(x_test)
    
    #模型融合中使用到的各个单模型
    clfs = [LogisticRegression(),
            RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
            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)]
    
    New_train,New_test = Ensemble_add_feature(x_train,x_test,y_train,clfs)
    
    clf = LogisticRegression()
    # clf = GradientBoostingClassifier(learning_rate=0.02, subsample=0.5, max_depth=6, n_estimators=30)
    clf.fit(New_train, y_train)
    y_emb = clf.predict_proba(New_test)[:, 1]
    
    print("Val auc Score of stacking: %f" % (roc_auc_score(y_test, y_emb)))
    
    Method  0
    Method  1
    Method  2
    Method  3
    Method  4
    Val auc Score of stacking: 1.000000
    
    展开全文
  • 模型融合方法概述

    千次阅读 2018-12-02 12:09:36
    模型融合方法概述 在比赛中提高成绩主要有3个地方 特征工程 调参 模型融合 1. Voting 模型融合其实也没有想象的那么高大上,从最简单的Voting说起,这也可以说是一种模型融合。假设对于一个二分类问题,有3个...

    模型融合方法概述

    在比赛中提高成绩主要有3个地方

    1. 特征工程
    2. 调参
    3. 模型融合

    1. Voting

    模型融合其实也没有想象的那么高大上,从最简单的Voting说起,这也可以说是一种模型融合。假设对于一个二分类问题,有3个基础模型,那么就采取投票制的方法,投票多者确定为最终的分类。

    2.Averaging

    对于回归问题,一个简单直接的思路是取平均。稍稍改进的方法是进行加权平均。权值可以用排序的方法确定,举个例子,比如A、B、C三种基本模型,模型效果进行排名,假设排名分别是1,2,3,那么给这三个模型赋予的权值分别是3/6、2/6、1/6 这两种方法看似简单,其实后面的高级算法也可以说是基于此而产生的,Bagging或者Boosting都是一种把许多弱分类器这样融合成强分类器的思想。

    3. Bagging

    Bagging就是采用有放回的方式进行抽样,用抽样的样本建立子模型,对子模型进行训练,这个过程重复多次,最后进行融合。大概分为这样两步:

    1. 重复K次
      有放回地重复抽样建模
      训练子模型

    2. 模型融合
      分类问题:voting
      回归问题:average

    Bagging算法不用我们自己实现,随机森林就是基于Bagging算法的一个典型例子,采用的基分类器是决策树。R和python都集成好了,直接调用。

    4. Boosting

    Bagging算法可以并行处理,而Boosting的思想是一种迭代的方法,每一次训练的时候都更加关心分类错误的样例,给这些分类错误的样例增加更大的权重,下一次迭代的目标就是能够更容易辨别出上一轮分类错误的样例。最终将这些弱分类器进行加权相加。引用加州大学欧文分校Alex Ihler教授的两页PPT

    同样地,基于Boosting思想的有AdaBoost、GBDT等,在R和python也都是集成好了直接调用。

    PS:理解了这两点,面试的时候关于Bagging、Boosting的区别就可以说上来一些,问Randomfroest和AdaBoost的区别也可以从这方面入手回答。也算是留一个小问题,随机森林、Adaboost、GBDT、XGBoost的区别是什么?

    5. Stacking

    Stacking方法其实弄懂之后应该是比Boosting要简单的,毕竟小几十行代码可以写出一个Stacking算法。我先从一种“错误”但是容易懂的Stacking方法讲起。

    Stacking模型本质上是一种分层的结构,这里简单起见,只分析二级Stacking.假设我们有3个基模型M1、M2、M3。

    1. 基模型M1,对训练集train训练,然后用于预测train和test的标签列,分别是P1,T1

    对于M2和M3,重复相同的工作,这样也得到P2,T2,P3,T3。

    1. 分别把P1,P2,P3以及T1,T2,T3合并,得到一个新的训练集和测试集train2,test2.

    1. 再用第二层的模型M4训练train2,预测test2,得到最终的标签列。

    Stacking本质上就是这么直接的思路,但是这样肯定是不行的,问题在于P1的得到是有问题的,用整个训练集训练的模型反过来去预测训练集的标签,毫无疑问过拟合是非常非常严重的,因此现在的问题变成了如何在解决过拟合的前提下得到P1、P2、P3,这就变成了熟悉的节奏——K折交叉验证。我们以2折交叉验证得到P1为例,假设训练集为4行3列

    将其划分为2部分

    用traina训练模型M1,然后在trainb上进行预测得到preb3和pred4

    在trainb上训练模型M1,然后在traina上进行预测得到pred1和pred2

    然后把两个预测集进行拼接

    对于测试集T1的得到,有两种方法。注意到刚刚是2折交叉验证,M1相当于训练了2次,所以一种方法是每一次训练M1,可以直接对整个test进行预测,这样2折交叉验证后测试集相当于预测了2次,然后对这两列求平均得到T1。 或者直接对测试集只用M1预测一次直接得到T1。 P1、T1得到之后,P2、T2、P3、T3也就是同样的方法。理解了2折交叉验证,对于K折的情况也就理解也就非常顺利了。所以最终的代码是两层循环,第一层循环控制基模型的数目,每一个基模型要这样去得到P1,T1,第二层循环控制的是交叉验证的次数K,对每一个基模型,会训练K次最后拼接得到P1,取平均得到T1。

    该图是一个基模型得到P1和T1的过程,采用的是5折交叉验证,所以循环了5次,拼接得到P1,测试集预测了5次,取平均得到T1。而这仅仅只是第二层输入的一列/一个特征,并不是整个训练集。再分析作者的代码也就很清楚了。也就是刚刚提到的两层循环。

    5.1 stacking方法

    将训练好的所有基模型对整个训练集进行预测,第j个基模型对第i个训练样本的预测值将作为新的训练集中第i个样本的第j个特征值,最后基于新的训练集进行训练。同理,预测的过程也要先经过所有基模型的预测形成新的测试集,最后再对测试集进行预测:

    下面我们介绍一款功能强大的stacking利器,mlxtend库,它可以很快地完成对sklearn模型地stacking。

    主要有以下几种使用方法吧:

    I. 最基本的使用方法,即使用前面分类器产生的特征输出作为最后总的meta-classifier的输入数据

    from sklearn import datasets
     
    iris = datasets.load_iris()
    X, y = iris.data[:, 1:3], iris.target
     
    from sklearn import model_selection
    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
    import numpy as np
     
    clf1 = KNeighborsClassifier(n_neighbors=1)
    clf2 = RandomForestClassifier(random_state=1)
    clf3 = GaussianNB()
    lr = LogisticRegression()
    sclf = StackingClassifier(classifiers=[clf1, clf2, clf3], 
                              meta_classifier=lr)
     
    print('3-fold cross validation:\n')
     
    for clf, label in zip([clf1, clf2, clf3, sclf], 
                          ['KNN', 
                           'Random Forest', 
                           'Naive Bayes',
                           'StackingClassifier']):
     
        scores = model_selection.cross_val_score(clf, X, y, 
                                                  cv=3, scoring='accuracy')
        print("Accuracy: %0.2f (+/- %0.2f) [%s]" 
              % (scores.mean(), scores.std(), label))

    II. 另一种使用第一层基本分类器产生的类别概率值作为meta-classfier的输入,这种情况下需要将StackingClassifier的参数设置为 use_probas=True。如果将参数设置为 average_probas=True,那么这些基分类器对每一个类别产生的概率值会被平均,否则会拼接。

    例如有两个基分类器产生的概率输出为:

    classifier 1: [0.2, 0.5, 0.3]

    classifier 2: [0.3, 0.4, 0.4]

    1) average = True :

    产生的meta-feature 为:[0.25, 0.45, 0.35]

    2) average = False:

    产生的meta-feature为:[0.2, 0.5, 0.3, 0.3, 0.4, 0.4]

    from sklearn import datasets
     
    iris = datasets.load_iris()
    X, y = iris.data[:, 1:3], iris.target
     
    from sklearn import model_selection
    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
    import numpy as np
     
    clf1 = KNeighborsClassifier(n_neighbors=1)
    clf2 = RandomForestClassifier(random_state=1)
    clf3 = GaussianNB()
    lr = LogisticRegression()
    sclf = StackingClassifier(classifiers=[clf1, clf2, clf3],
                              use_probas=True,
                              average_probas=False,
                              meta_classifier=lr)
     
    print('3-fold cross validation:\n')
     
    for clf, label in zip([clf1, clf2, clf3, sclf], 
                          ['KNN', 
                           'Random Forest', 
                           'Naive Bayes',
                           'StackingClassifier']):
     
        scores = model_selection.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.91 (+/- 0.06) [Random Forest]
    Accuracy: 0.92 (+/- 0.03) [Naive Bayes]
    Accuracy: 0.94 (+/- 0.03) [StackingClassifier]
    

    III. 另外一种方法是对训练基中的特征维度进行操作的,这次不是给每一个基分类器全部的特征,而是给不同的基分类器分不同的特征,即比如基分类器1训练前半部分特征,基分类器2训练后半部分特征(可以通过sklearn 的pipelines 实现)。最终通过StackingClassifier组合起来。

    from sklearn.datasets import load_iris
    from mlxtend.classifier import StackingClassifier
    from mlxtend.feature_selection import ColumnSelector
    from sklearn.pipeline import make_pipeline
    from sklearn.linear_model import LogisticRegression
     
    iris = load_iris()
    X = iris.data
    y = iris.target
     
    pipe1 = make_pipeline(ColumnSelector(cols=(0, 2)),
                          LogisticRegression())
    pipe2 = make_pipeline(ColumnSelector(cols=(1, 2, 3)),
                          LogisticRegression())
     
    sclf = StackingClassifier(classifiers=[pipe1, pipe2], 
                              meta_classifier=LogisticRegression())
     
    sclf.fit(X, y)

    output

    StackingClassifier(average_probas=False,
              classifiers=[Pipeline(memory=None,
         steps=[('columnselector', ColumnSelector(cols=(0, 2), drop_axis=False)), ('logisticregression', LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
              intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
              pen...='l2', random_state=None, solver='liblinear', tol=0.0001,
              verbose=0, warm_start=False))])],
              meta_classifier=LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
              intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
              penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
              verbose=0, warm_start=False),
              store_train_meta_features=False, use_clones=True,
              use_features_in_secondary=False, use_probas=False, verbose=0)

    StackingClassifier 使用API及参数解析:

    StackingClassifier(classifiers, meta_classifier, use_probas=False, average_probas=False, verbose=0, use_features_in_secondary=False)

    参数:

    classifiers : 基分类器,数组形式,[cl1, cl2, cl3]. 每个基分类器的属性被存储在类属性 self.clfs_. meta_classifier : 目标分类器,即将前面分类器合起来的分类器

    use_probas : bool (default: False) ,如果设置为True, 那么目标分类器的输入就是前面分类输出的类别概率值而不是类别标签

    average_probas : bool (default: False),用来设置上一个参数当使用概率值输出的时候是否使用平均值。

    verbose : int, optional (default=0)。用来控制使用过程中的日志输出,当 verbose = 0时,什么也不输出, verbose = 1,输出回归器的序号和名字。verbose = 2,输出详细的参数信息。verbose > 2, 自动将verbose设置为小于2的,verbose -2.

    use_features_in_secondary : bool (default: False). 如果设置为True,那么最终的目标分类器就被基分类器产生的数据和最初的数据集同时训练。如果设置为False,最终的分类器只会使用基分类器产生的数据训练。

    属性:

    clfs_ : 每个基分类器的属性,list, shape 为 [n_classifiers]。 meta_clf_ : 最终目标分类器的属性

    方法:

    fit(X, y)
    fit_transform(X, y=None, fit_params)
    get_params(deep=True),如果是使用sklearn的 GridSearch方法,那么返回分类器的各项参数。 predict(X)
    predict_proba(X)

    score(X, y, sample_weight=None), 对于给定数据集和给定label,返回评价accuracy

    set_params(params),设置分类器的参数,params的设置方法和sklearn的格式一样。

    参考链接:

    https://zhuanlan.zhihu.com/p/25836678

    https://blog.csdn.net/willduan1/article/details/73618677

    展开全文
  • Ensemble Learning-基于集成学习的模型融合-Python实现

    万次阅读 多人点赞 2017-07-16 19:08:36
    模型融合常用方法。 1 Voting 2 Averaging 3 Ranking 4 Binning 5 Bagging 6 Boosting 7 Stacking 8 Blending
  • keras模型融合

    2018-11-29 18:35:00
    keras模型融合 keras模型融合 posted on 2018-11-29 18:35 luoganttcc 阅读(...) 评论(...) 编辑 收藏 ...
  • 基于局部行为模型融合的适应模型构建技术
  • 基于同步核的BPMN模型融合
  • 模型融合Blending 和 Stacking

    千次阅读 2020-03-03 00:19:54
    前言 机器学习中很多训练模型通过融合方式都有可能使得准确率等评估指标有所提高,这一块有很多...不同的模型有各自的长处,具有差异性,而模型融合可以使得发挥出各个模型的优势,让这些相对较弱的模型(学习器)通...
  • 为了提高光伏发电输出功率的预测精度和可靠性,本文提出一种基于Stacking模型融合的光伏发电功率预测方法.选取某光伏电站温度、湿度、辐照度等历史实测数据为研究对象,在将光伏发电功率数据进行特征交叉以及基于...
  • 模型融合xgboost+lr

    2018-10-18 14:07:15
    新网银行的统计建模比赛,使用xgboost +lr模型融合,先用xgboost提取特征,再使用lr分类。
  • 为了解决在复杂背景以及人流密集且互相遮挡的场景下, 对人流密度进行估计精度低的问题, 提出了基于YOLOv3增强模型融合的方法进行人流密度估计. 首先将数据集分别进行头部标注和身体标注, 生成头部集和身体集. 然后用...
  • 基于粒子滤波的模型融合用于预测
  • 针对单模型评价图像质量容易产生过拟合的问题, 提出基于多模型融合的高光谱图像质量评价算法。以图像噪声、模糊度和云含量为降质特征, 建立遥感图像主观评价库, 分别选用支持向量回归方法和集成决策树方法对带有评...
  • pytorch之多模型融合

    千次阅读 2020-02-24 10:36:07
    1.挑选结构较简单的网络层次上的神经网络参与到多模型融合 2. 多模型融合+迁移学习 辅助模型的融合 2.多模型融合的方法 1.结果多数表决 2.结果直接平均 3.结果加权平均 3.pytorch 之多模型融合实战(vgg16+resnet50...
  • 机器学习模型优化之模型融合

    万次阅读 多人点赞 2018-01-07 15:37:24
    前言:在机器学习训练完模型之后我们要考虑模型的效率问题,常用的模型效率分析手段有: 研究模型学习曲线,判断模型是否过拟合或者...模型融合模型融合就是训练多个模型,然后按照一定的方法集成过个模型,应为...
  • 机器学习集成学习与模型融合.pdf
  • 主要介绍了使用keras实现densenet和Xception的模型融合,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • dw数据挖掘——模型融合.key
  • Task05:模型融合

    2020-09-27 23:53:11
    Task05:模型融合
  • 为此,提出一种基于极限梯度提升(XGBoost)与Stacking模型融合的短期母线负荷预测方法。基于XGBoost建立多个母线负荷预测元模型,组合构成Stacking模型融合的元模型层,连接一个XGBoost模型对元模型进行融合,整体...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 140,832
精华内容 56,332
关键字:

模型融合