比赛总结---对于常见集成学习方法的思考

前言

前段时间参加了招商银行的Fintech 数据竞赛,主题是关于业务量的时间序列预测。我总共尝试使用了3种不同类型的方式进行数据的建模,第一种是传统的时间序列建模方法,如ARIMA,第二种是机器学习的方法,第三种是深度学习方法,主要用到了LSTM进行建模。总体上来看,传统方法和深度学习方法在这个任务中表现都不是很理想,机器学习的效果是相对最好的,在机器学习中,我主要使用了3种集成学习的算法,分别是Random Forest,GBDT以及XGBoost,当然这么说不太准确,因为XGBoost并不能算成一种单独的算法,应该说成是GBDT的一种高效实现或者工业实现,这里大家明白我的意思就好。下面我来大概总结一下在使用这3种方法进行建模预测上的一些思考。如果大家对我的完整比赛代码感兴趣,可以查看我的github,具体的比赛数据如果需要可以私信我。

1.Random Forest

理论背景
相信只要是对机器学习有一定了解的同学都一定听说过random forest,中文名随机森林,这是一种非常经典以及有效的集成学习(ensemble learning)方法。

它从属于bagging派,这里稍微解释一下bagging, bagging的意思就是说,我通过使用bootstrap方法(重采样)从原始训练集中采样多组训练集{x1,x2,x3…xn}, 然后用这n个数据集训练n个不同的弱学习器(比如n个线形模型),然后让这n个模型分别对测试集进行预测,得到n组不同的结果然后取平均作为最终的预测结果。这种多个分类器进行平均的方法不仅可以通过结合多个模型来提升最终模型的预测精度,同时也有效地降低模型的模型的variance, 使得模型的预测效果具有更好的鲁棒性。

但是bagging的一个比较大的问题就是如果我们的每个弱学习器都十分相似,那么做bagging的意义可能就不大了,考虑一个极端例子,当每个弱学习器完全一样,那么集成的意义就消失了。总之,对于bagging方法,保证子模型的差异性非常重要,这种差异不仅体现在子模型的特征选择,也可以是算法的不同,比如我们在结合多个子模型做预测时,通常会选择完全不同的算法,比如选择一个线性回归,一个树模型,一个神经网络去做集成。

那么Random Forest是如何保证各个弱学习器的差异性的呢?关键点就在于对于Random Forest, 在生成每棵子树的过程中,每个节点的分类时,并不会考虑全部的节点,而是随机选取特定比例的特征,比如总数是N个特征,每次split都只考虑sqrt(N)个特征,通过这个方法,来尽可能保证每棵子树具有足够大的差异性。可以说Random Forest 是对传统bagging算法的一个提升。

实际使用
我使用的Python中的一个著名的机器学习包sklearn,直接调用其中的RandomForestRegressor接口(该任务被转化为回归问题)。

from sklearn.ensemble import RandomForestRegressor

下面是实际使用中的一些注意点:
1.在数据量很大时,使用random forest比较费时。
因为参数max_depth(树的最大深度)在默认情况下会不断加深直到每个叶子结点包含的样本个数小于min_samples_split(节点继续分裂的最小样本数)为止,比如默认值为2,就是说如果某个叶子结点的样本数大于2,就会不断分裂。那么对于数据量很大的训练集而言,使用默认参数来训练模型的时间是非常长的。因此我们对于这两个参数,在样本量很大的情况下,有必要进行设定,比如设定max_depth=10.

2.在设定n_estimators时,可以尽可能选的大一些。因为使用random forest方法不需要过多的考虑overfitting的问题,比如设置n_estimators=500或1000都没有问题,当然具体还是要以具体情况而定。

3.默认情况下,默认使用所有的特征,max_features=‘auto’, 我们可以选择将其改为‘sqrt’ 或着 ‘log2’, 分别代表每次split时选择N个特征中的sqrt(N)个 和 log2(N)个。特别是当数据集的特征数特别多时,可以选择修改这个参数。

2.GBDT

理论背景
接下来我们来说一下GBDT,全名是Gradient Boosting Decision Tree, ,中文可以叫做梯度提升树。不夸张的说,GBDT可以被当作是最好的机器学习算法之一。几乎所有的比赛中,我都会尝试使用GBDT作为baseline,效果都非常不错。不同于random forest,GBDT属于boosting流派。boosting,总结来说就是learn from error,从错误中学习。除了GBDT,早期表经典的boosting算法有比如Adaboost,其一般被用在分类问题中,基本思想就是对于当前分类器分类错误的样本,在下一次模型训练时被给予更高的权重,从而使模型能够从错误中不断改善。那么对于GBDT而言,它是怎么从错误中学习的呢?

我们可以先思考一个最简单的回归问题,假设我们已经有了一个弱学习器,一个CART树模型,那么如果我们想要提升它的性能,该怎么做呢?一个直觉的思路就是我们可以先去计算使用该模型得到的预测值{x1_hat,x2_hat,…xm_hat}, 然后拿真实值{y1,y2,…ym}与它做差,拿得到的残差作为下一个学习器的回归目标,再训练下一棵树,不断重复这个过程并不断地将之前的模型相加得到最终的模型。通过这个过程,最终模型与真实值的距离越来越小,预测精度不断提升。

但是,上面的这种拟合残差的方法只能针对回归问题,其他问题比如分类问题中,根本就没有所谓残差的概念,那么这时我们该怎么去拟合损失呢?针对这个问题,GBDT的创造者Freidman提出使用损失函数对当前模型预测值的负梯度来作为新的学习器的拟合对象。这也是这个算法被称为梯度提升树。事实上当我们选择使用MSE作为损失函数公式时,我们的损失函数对当前模型的预测值的负梯度恰好就是我们的残差。因此可以说GBDT这个算法将我在上面这个简单例子中的拟合残差的想法拓展成为一种具有普遍意义的方法,可以用于各种各样的损失函数(一阶可微)。下面完整展示一下GBDT的算法流程(回归)
在这里插入图片描述
实际使用
这里依然以Python sklearn 包中封装的GBDT作为例子。

from sklearn.ensemble import GradientBoostingRegressor

1.首先由于每一颗树的生成都依赖于前一颗树,因此多棵树之间无法实现并行,相对来说训练的时间会比较长。
2.不同于bagging, GBDT 包括其他的boosting算法都存在过拟合的问题,对于GBDT,如果你的n_estimators过大,就会存在过拟合的风险,这一点在调参时需要注意。
3.为了防止过拟合问题,除了2中控制弱学习器的个数,另一种方式叫做Stochastic Gradient Boosting, 简单来说就是每次训练弱学习器时只选择训练集的一部分进行训练。维基百科上的解释如下:

Specifically, he proposed that at each iteration of the algorithm, a base learner should be fit on a subsample of the training set drawn at random without replacement.Friedman observed a substantial improvement in gradient boosting’s accuracy with this modification.

我在实际应用中并没用修改这个参数,大家在之后的使用中可以尝试一下。
4.处理上面提到的解决过拟合的方法,还有其他的解决办法比如在模型相加时添加一个正则化系数,其实就是参数中的learning_rate, 除此之外,还可以对每棵树的深度与节点做剪枝,这就需要结合具体情况了。

3.XGBoost

关于XGBoost,总结来说,就是GBDT的优化版本。关于XGBoost,这部分我想主要讨论一下XGBoost相较于GBDT的不同或者说提升点在哪里。

a.首先最重要的就是优化目标(或者损失函数)

GBDT:
GBDT的思路在于给定损失函数的形式比如MSE后,每一个新的基学习器(树结构)的 学习目标都是损失函数关于现有模型预测值的负梯度。

XGBoost
1.XGBoost对原损失函数进行的二阶泰勒展开,利用一阶与二阶导数的表达式来近似损失函数。事实上,二阶的泰勒展开不仅可以精准地逼近真实的损失函数,同时也可以近似更加广泛的的损失函数,从而保证损失函数的选择可以更加灵活,只要满足函数支持1,2阶可导。
2.除此之外,相比于GBDT,XGBoost对于过拟合问题做更多的优化,比如在目标函数中添加正则项,同时在每棵树相加时增加衰减系数,以及在构建树时借鉴random forest的feature sub-sampling的思想。

b.接下来就是训练过程(基学习器的生成)

GBDT
传统的GBDT选择CART树作为基学习器,在每棵树训练的过程中采用贪心搜索去寻找最优切分点,虽然这种方法可以更加准确地找到最优的树结构,但是不可避免的就是效率低,计算开销大。

XGBoost
1.在基学习器的选择上,GBDT不仅支持CART树,同时还支持线形分类器。同时,对于树结构的生成,除了原始的贪心算法之外,原论文中还提出了一种近似算法,即在选择切分点的时候不选择遍历所有值,而是根据特征的分布选取分位数作为候选切分点。在提出候选切分点时,作者提出了两种不同的策略,一种叫做Global,即‘全局切分’: 学习每棵树前就提出候选切分点,并在每次分裂时都采用这种分割,另一种叫Local,相对地,每次分裂都重新提出候选切分点。作者还在测试数据集上对两种不同的策略做了比较,结果发现:
在这里插入图片描述
即当选择全局策略时,如果能够在开始选取足够多的候选点,那么就精度而言与局部的策略可以保持在同一水平。

不仅如此,在使用近似算法选取候选切分点时,并不仅仅简单地按照样本个数进行分位,而是以二阶导数值作为权重进行分位的划分。这里作者提出了Weighted Quantile Sketch算法,关于这部分内容,我就不详细展开了,有兴趣的朋友可以阅读一下原文

2.相比于GBDT,XGBoost在对缺失值的处理方面也做了优化。传统的GBDT并没有设计对缺失值进行处理,而XGBoost设计了一个缺失值处理的策略。被称为稀松感知算法,简单来说,在XGBoost构建树的过程中,只利用不存在缺失值的数据行。但是XGBoost又为缺失值确定了一条default path, 在每个节点处都会有一个明确的将缺失值进行分类的direction(左或右),而这个最优的路径是通过数据学到的。下面是原文中的一个示例。
在这里插入图片描述
c.上面两部分主要从策略以及算法两个方法讨论了XGBoost相较于GBDT的不同点。除此之外,XGBoost在工程实现角度也是做了极大的提升,大致可以归结为如下的3个方面。
1.列块并行学习
2.缓存访问
3.‘核外’块计算
关于这部分内容,我认为自己的理解还不够到位,这里就先不做展开了。

实际使用
关于XGBoost的使用,自然也是有现成的接口供我们使用,除了原生的接口,熟悉sklearn的朋友也可以使用sklearn接口, 这里我也以sklearn接口下的调用(回归问题)作为例子

from xgboost import XGBRegressor

当我们使用XGBoost时,调参是一个非常重要的工作,相对于其他简单的模型比如岭回归或者LASSO,XGBoost需要预先设置大量的超参数,而超参数的设定一方面基于经验,一方面也需要具体问题具体分析。

对于XGBoost, 完整的参数列表参考这里
其中,我认为比较重要的几个特征如下:
1.n_estimators & learning_rate 两者分别代表基学习器的数量以及学习率,这两个参数是控制模型的泛化程度,防止模型过拟合的重要参数,对于学习率的选择,我建议一般选择0.1是比较合适的,而n_estimator的选择,需要具体情况以及其他参数而定。

2.booster, 指的是基学习器的种类,正如前面部分所说,XGBoost不仅支持树结构,同时也支持线形结构,一般情况下,线形结构的效果都比较差,类似于岭回归或套索,但是也并非一定。在这次比赛中的第一部分任务中,我使用‘gblinear’的的模型效果要好于‘gbtree’以及‘dart’,原因可能在于任务本身并不复杂,同时数据量相对较少,所以选择相对简单的线性模型作为弱学习器来进行堆叠反而防止了过拟合的发生。但是如果是在相对比较复杂的任务,数据量很大,特征充裕的情况下,选择树结构作为弱学习器一般会取得更好的效果。但是要注意的是,如果你的基学习器选择了相对复杂的树模型,那么在设定n_estimator时需要尽量将值调小一些。

3.max_depth,顾名思义,每棵树的最大深度,过于复杂的树会严重抑制后续boosting的效果,因此我一般会选择设定3到10之间,当然也是需要具体情况具体分析,一般如果要设定的话,尽量选择偏小一些。

4.subsample, 每次训练模型所用的训练集ratio, 比如设定0.8。
5.colsample_bytree,构建每棵树时使用的特征个数比例,比如0.5,即随机选择一半的特征用于树的生成。这里也是作者在原文中特别提到的借鉴random forest的思想,一方面可以抑制过拟合,一方面也提升了模型的并行运算的效率。

OKK,以上就是这篇总结的全部内容了,感谢大家的阅读。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值