模型融合的一些思路集锦

前言

  • 特征工程
  • 调参
  • 模型融合

我觉得是机器学习的三大神器了,我记得前面有些博客介绍过超参数调参方法、特征离散化等特征工程的一些知识。但是还没有正式介绍过模型融合的相关知识。

似乎大家对模型融合没有太多认识哈,我其实接触的也少,平时也只是简单的多模型加权平均,适应于不同模型可能存在的过拟合互补;又或者使用bagging自举算法,做模型融合(我这多说几句,我平常模型融合的基学习器用的是LR,主要做分类,似乎没做过回归,回归怎么融合,我后面会给出思路的)

集成学习主要分为 bagging, boosting 和 stacking方法(看我集成回归那一博客,boosting(GBDT)和bagging(RF)怎么实现的内容过程有原理,也有代码)。本文不涉及到各个算法原理层次的深度,目的在于从宏观上帮助理解这几个模型融合方法。然后就开始介绍吧!

模型融合

一、Voting

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

二、Averaging

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

三、Bagging

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

1. 重复K次

  • 有放回地重复抽样建模
  • 训练子模型

2.模型融合

  • 分类问题:voting
  • 回归问题:average

其实就是说,给定一个大小为n的训练集 D,Bagging算法从中均匀、有放回地选出 m个大小为 n' 的子集Di,作为新的训练集。在这 m个训练集上使用分类、回归等算法,则可得到 m个模型,再通过取平均值、取多数票等方法综合产生预测结果,即可得到Bagging的结果。

比如说 随机森林就是基于Bagging算法的一个典型例子,采用的基分类器是CART二元决策树。python可以直接调用。

四、Boosting

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

看这个很经典的图片,通过划分得到不同的分类器,他是记录上次划分错误的案例,重新划分得到多个弱分类器(Cart树),然后就combine一起。

 

想忍不住多说几句Boosting算法

1)“三个臭皮匠顶个诸葛亮”,一堆弱分类器的组合就可以成为一个强分类器;

2)“知错能改,善莫大焉”,不断地在错误中学习,迭代来降低犯错概率

当然,要理解好Boosting的思想,首先还是从弱学习算法和强学习算法来引入:

1)强学习算法:存在一个多项式时间的学习算法以识别一组概念,且识别的正确率很高;

2)弱学习算法:识别一组概念的正确率仅比随机猜测略好;

Kearns & Valiant证明了弱学习算法与强学习算法的等价问题,如果两者等价,只需找到一个比随机猜测略好的学习算法,就可以将其提升为强学习算法。

那么是怎么实现“知错就改”的呢?

Boosting算法,通过一系列的迭代来优化分类结果,每迭代一次引入一个弱分类器,来克服现在已经存在的弱分类器组合的shortcomings。(这句话有点不太理解,但是肯定是利用上一次的错误来提升自个儿

  在Adaboost算法中,这个shortcomings的表征就是权值高的样本点

  在Gradient Boosting算法中,这个shortcomings的表征就是梯度,对于GBDT 后续的循环都是用训练产生的(误差残差 - eps*预测值)作为目标结果进行训练 每个后续的决策树是在前面决策树 遗留的错误上进行训练

无论是Adaboost还是Gradient Boosting,都是通过这个shortcomings来告诉学习器怎么去提升模型,也就是“Boosting”这个名字的由来吧

随机森林、Adaboost、GBDT、XGBoost的区别是什么?

待更吧---- https://www.cnblogs.com/zhubinwang/p/5170087.html 先看看呗

 

五、Stacking

之前一直对stacking一知半解,找到的资料也介绍的很模糊。。所以有多看了几篇文章,然后来此写篇博客,加深一下印象,顺便给各位朋友分享一下。

stacking的过程有一张图非常经典,如下:

虽然他很直观,但是没有语言描述确实很难搞懂。

首先从整个数据集分割出训练集Training Data,Test Data,假设分别为10000行和3000行。记住了!(还有区分 加重字体

然后呢对Training Data交叉训练,就是图形的上半部分,用一个基础模型进行5折交叉验证。如:用XGBoost作为基础模型Model1,5折交叉验证就是先拿出四折作为训练数据training data,另外一折作为测试数据(验证数据)testing data(区分开Test Data和testing data 好吗!)。注意:在stacking中此部分数据会用到整个Training Data

其实每一次交叉验证其实就是对Training Data进行划分,在每一次的交叉验证中training data将会是8000行,testing data是2000行。每一次的交叉验证包含两个过程,1. 基于training data训练模型;2. 基于training data训练生成的模型对testing data进行预测。在整个第一次的交叉验证完成之后我们将会得到关于当前testing data的预测值,这将会是一个一维2000行的数据,记为a1。

注意!在这部分操作完成后,我们还要对数据集原来的整个Test Data进行预测,这个过程会生成3000个预测值,这部分预测值将会作为下一层模型Test Data的一部分,记为b1。

因为我们进行的是5折交叉验证,所以以上提及的过程将会进行五次,最终会生成针对testing data数据预测的5列2000行的数据a1,a2,a3,a4,a5,对Test Data的预测会是5列3000行数据b1,b2,b3,b4,b5。

在完成对Model1的整个步骤之后,我们可以发现a1,a2,a3,a4,a5其实就是对原来整个Training Data的预测值,将他们拼凑起来,会形成一个10000行一列的矩阵,记为A1。而对于b1,b2,b3,b4,b5这部分数据,我们将各部分相加取平均值,得到一个3000行一列的矩阵,记为B1。

以上就是stacking中一个模型的完整流程,stacking中同一层通常包含多个模型,假设还有Model2: LR,Model3:RF,Model4: GBDT,Model5:SVM,对于这四个模型,我们可以重复以上的步骤,在整个流程结束之后,我们可以得到新的A2,A3,A4,A5,B2,B3,B4,B5矩阵。

在此之后,我们把A1,A2,A3,A4,A5并列合并得到一个10000行五列的矩阵作为Training Data,B1,B2,B3,B4,B5并列合并得到一个3000行五列的矩阵作为Test Data。让下一层的模型,基于他们进一步训练。

以上即为stacking的完整步骤!

多个模型融合:

    TRAIN_X=train_X.copy() # 融合后的特征
    TEST_X=test_X.copy()
    #多模型的stacking算法
    for clf in clfs:
        # 分别使用rf lr svm
        print(clf)
        for train_index, test_index in kf.split(train_Y):
            trainX=train_X[train_index, :]
            trainY=train_Y[train_index]
            testX=train_X[test_index, :]
            testY=train_Y[test_index]
            clf.fit(trainX, trainY)
            
            CLF.append(clf)
            
            pred=clf.predict(testX)
            
            # 每一个模型的pred作为一个特征
            PRD=np.hstack((PRD, pred))
            score=compute_loss(testY, pred)
            print('cross_compute_loss:{}'.format(score))

            # 测试集预测,结果取平均
            pred_test=clf.predict(test_X)
            PRD_TEST.append(pred_test)

        # 怎么组合不了?试了很多种。原来是要reshape(-1,1)
        TRAIN_X=np.concatenate((TRAIN_X, PRD.reshape(-1,1)), axis=1)
        TEST_X=np.concatenate((TEST_X, np.array(PRD_TEST).mean(axis=0).reshape(-1,1)), axis=1)
        
        print(TRAIN_X.shape, TEST_X.shape)

        PRD=[]
        PRD_TEST=[]
        print('\n')

代码是两层循环。第一层循环控制基模型的数目,每一个基模型要这样去得到P1,T1以扩充维度;第二层循环控制的是交叉验证的次数K,对每一个基模型,会训练K次最后拼接得到P1,取平均得到T1。就得到一个新的融合模型特征之后的新的数据集哈!训练集TRAIN_X和测试集TEST_X同时扩充了模型预测的维度!其实训练集扩充维度(合并merge)很好理解,但是测试集维度扩充(平均average)也得要呀!

还有一个有趣的解释 

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

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

mlxtend(stacking)集成库

另外python好像有集成好的一款功能强大的stacking利器,mlxtend库,它可以很快地完成对sklearn模型地stacking。

我就不介绍了 因为我没看懂咋用 但我贴个链接出来 https://blog.csdn.net/willduan1/article/details/73618677

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值