Boosting 集成算法中Adaboost、GBDT与XGBoost的区别

Boosting 集成算法中Adaboost、GBDT与XGBoost的区别

所谓集成学习,是指构建多个分类器(弱分类器)对数据集进行预测,然后用某种策略将多个分类器预测的结果集成起来,作为最终预测结果。通俗比喻就是“三个臭皮匠赛过诸葛亮”,或一个公司董事会上的各董事投票决策,它要求每个弱分类器具备一定的“准确性”,分类器之间具备“差异性”。

集成学习根据各个弱分类器之间有无依赖关系,分为Boosting和Bagging两大流派:

Boosting流派,各分类器之间有依赖关系,必须串行,比如Adaboost、GBDT(Gradient Boosting Decision Tree)、Xgboost

Bagging流派,各分类器之间没有依赖关系,可各自并行,比如随机森林(Random Forest)

而著名的Adaboost作为boosting流派中最具代表性的一种方法。

Adaboost

AdaBoost,是英文”Adaptive Boosting”(自适应增强)的缩写,由Yoav Freund和Robert Schapire在1995年提出。它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数。

具体说来,整个Adaboost 迭代算法就3步:

  1. 初始化训练数据的权值分布。如果有N个样本,则每一个训练样本最开始时都被赋予相同的权值:1/N。

  2. 训练弱分类器。具体训练过程中,如果某个样本点已经被准确地分类,那么在构造下一个训练集中,它的权值就被降低;相反,如果某个样本点没有被准确地分类,那么它的权值就得到提高。然后,权值更新过的样本集被用于训练下一个分类器,整个训练过程如此迭代地进行下去。

  3. 将各个训练得到的弱分类器组合成强分类器。各个弱分类器的训练过程结束后,加大分类误差率小的弱分类器的权重,使其在最终的分类函数中起着较大的决定作用,而降低分类误差率大的弱分类器的权重,使其在最终的分类函数中起着较小的决定作用。换言之,误差率低的弱分类器在最终分类器中占的权重较大,否则较小。

GBDT(Gradient Boost Decision Tree)

另一种boosting方法GBDT(Gradient Boost Decision Tree),则与AdaBoost不同,GBDT每一次的计算是都为了减少上一次的残差,进而在残差减少(负梯度)的方向上建立一个新的模型。

boosting集成学习由多个相关联的决策树联合决策,什么叫相关联?举个例子

  1. 有一个样本[数据->标签]是:[(2,4,5)-> 4]

  2. 第一棵决策树用这个样本训练的预测为3.3

  3. 那么第二棵决策树训练时的输入,这个样本就变成了:[(2,4,5)-> 0.7]

  4. 也就是说,下一棵决策树输入样本会与前面决策树的训练和预测相关

很快你会意识到,Xgboost为何也是一个boosting的集成学习了。

而一个回归树形成的关键点在于:

  • 分裂点依据什么来划分(如前面说的均方误差最小,loss);

  • 分类后的节点预测值是多少(如前面说,有一种是将叶子节点下各样本实际值得均值作为叶子节点预测误差,或者计算所得)

至于另一类集成学习方法,比如Random Forest(随机森林)算法,各个决策树是独立的、每个决策树在样本堆里随机选一批样本,随机选一批特征进行独立训练,各个决策树之间没有啥关系。本文暂不展开介绍。

说到Xgboost,不得不先从GBDT(Gradient Boosting Decision Tree)说起。而且前面说过,两者都是boosting方法(如图所示:Y = Y1 + Y2 + Y3)

咱们来看个年龄预测的例子。

简单起见,假定训练集只有4个人:A,B,C,D,他们的年龄分别是14,16,24,26。其中A、B分别是高一和高三学生;C,D分别是应届毕业生和工作两年的员工。

如果是用一棵传统的回归决策树来训练,会得到如下图所示结果:

现在我们使用GBDT来做这件事,由于数据太少,我们限定叶子节点最多有两个,即每棵树都只有一个分枝,并且限定只学两棵树。

我们会得到如下图所示结果:

在第一棵树分枝和图1一样,由于A,B年龄较为相近,C,D年龄较为相近,他们被分为左右两拨,每拨用平均年龄作为预测值。

  • 此时计算残差(残差的意思就是:A的实际值 - A的预测值 = A的残差),所以A的残差就是实际值14 - 预测值15 = 残差值-1。

  • 注意,A的预测值是指前面所有树累加的和,这里前面只有一棵树所以直接是15,如果还有树则需要都累加起来作为A的预测值。

残差在数理统计中是指实际观察值与估计值(拟合值)之间的差。“残差”蕴含了有关模型基本假设的重要信息。如果回归模型正确的话, 我们可以将残差看作误差的观测值。

进而得到A,B,C,D的残差分别为-1,1,-1,1。

然后拿它们的残差代替A B C D的原值-1、1、-1、1,到第二棵树去学习,第二棵树只有两个值1和-1,直接分成两个节点,即A和C分在左边,B和D分在右边,经过计算(比如A,实际值-1 - 预测值-1 = 残差0,比如C,实际值-1 - 预测值-1 = 0),此时所有人的残差都是0。

残差值都为0,相当于第二棵树的预测值和它们的实际值相等,则只需把第二棵树的结论累加到第一棵树上就能得到真实年龄了,即每个人都得到了真实的预测值。

换句话说,现在A,B,C,D的预测值都和真实年龄一致了。Perfect!

A: 14岁高一学生,购物较少,经常问学长问题,预测年龄A = 15 – 1 = 14

B: 16岁高三学生,购物较少,经常被学弟问问题,预测年龄B = 15 + 1 = 16

C: 24岁应届毕业生,购物较多,经常问师兄问题,预测年龄C = 25 – 1 = 24

D: 26岁工作两年员工,购物较多,经常被师弟问问题,预测年龄D = 25 + 1 = 26

GBDT小结

提升树方法是利用加法模型与前向分布算法实现整个优化学习过程。Adaboost的指数损失和回归提升树的平方损失,在前向分布中的每一步都比较简单。但对于一般损失函数而言(比如绝对损失),每一个优化并不容易。

针对这一问题。Freidman提出了梯度提升(gradient boosting)算法。该算法思想:

利用损失函数的负梯度在当前模型的值作为回归问题提升树算法中残差的近似值,拟合一个回归树。

损失函数的负梯度为:

[ L ( y ( i ) , f ( x ( i ) ) ) f ( x ( i ) ) ] f ( x ) = f k 1 ( x ) r m , i

注:需要注意“利用损失函数的负梯度在当前模型的值作为回归问题提升树算法中残差的近似值”,这正是GBDT与XGBoost的最本质区别之一,GBDT采用利用损失函数的一阶负梯度(偏导)来代理残差,GBDT典型特点包括使用绝对值损失函数,使用损失函数的一阶负梯度来当做残差近似值。


XGBoost则对GBDT做了进一步改造,虽然是GBDT算法的一种变体实现,但又做了很多改变。不再局限于绝对值损失函数,支持logistic损失函数等,使用损失函数的一阶、二阶偏导数,利用泰勒展开做损失函数近似值。

这里写图片描述

算法解释:

  1. 第(1)步初始化,估计使损失函数极小化的常数值(是一个只有根结点的树);
  2. 第(2)(a)步计算损失函数的负梯度在当前模型的值,将它作为残差的估计。(对于平方损失函数,他就是残差;对于一般损失函数,它就是残差的近似值)
  3. 第(2)(b)步估计回归树的结点区域,以拟合残差的近似值;
  4. 第(2)(c)步利用线性搜索估计叶结点区域的值,使损失函数极小化;
  5. 第(2)(d)步更新回归树。

XGBoost

XGBoost树的定义

本节的示意图基本引用自xgboost原作者陈天奇的讲座PPT中。

举个例子,我们要预测一家人谁是谁,则可以先通过年龄区分开小孩和大人,然后再通过性别区分开是男是女,如下图所示。

就这样,训练出了2棵树tree1和tree2,类似之前gbdt的原理,两棵树的结论累加起来便是最终的结论,所以小孩的预测分数就是两棵树中小孩所落到的结点的分数相加:2 + 0.9 = 2.9。爷爷的预测分数同理:-1 + (-0.9)= -1.9。具体如下图所示

恩,你可能要拍案而起了,惊呼,这不是跟上文介绍的gbdt乃异曲同工么?

事实上,如果不考虑工程实现、解决问题上的一些差异,xgboost与gbdt比较大的不同就是目标函数的定义。

事实上,XGBoost官网上也说XGBoost是GBDT的是一种实现,但我个人认为XGBoost与传统的GBDT在实现方式上还是有不少区别,见下面分析

XGBoost的目标函数如下图所示:

其中红色箭头所指向的L 即为损失函数(比如平方损失函数: ( y i , y ^ i ) = ( y i y ^ i ) 2 ,或logistic损失函数或hinge损失函数或者自定义的损失函数(调用XGBoost包时候则需要输入该自定义损失函数的一阶、二阶损失函数)

  • 红色方框所框起来的是正则项(包括L1正则、L2正则)

  • 红色圆圈所圈起来的为常数项

  • 对于f(x),xgboost利用泰勒展开三项,做一个近似

我们可以很清晰地看到,最终的目标函数只依赖于每个数据点的在误差函数上的一阶导数和二阶导数。

额,峰回路转,突然丢这么大一个公式,不少人可能瞬间就懵了。没事,下面,咱们来拆接下这个目标函数。

XGBoost目标函数

首先,再次明确下我们的目标,是希望建立K个回归树,使得树群的预测值尽量接近真实值(准确率)而且有尽量大的泛化能力(更为本质的东西)。

从数学角度看这是一个泛函最优化,多目标,把目标函数简化下:

L ( ϕ ) = γ T + 1 2 w 2

T表示叶子节点的个数,w表示节点的数值。直观上看,目标要求预测误差尽量小,且叶子节点T尽量少,节点数值w尽量不极端。

插一句,一般的目标函数都包含下面两项

其中,误差函数鼓励我们的模型尽量去拟合训练数据,使得最后的模型会有比较少的 bias。而正则化项则鼓励更加简单的模型。因为当模型简单之后,有限数据拟合出来结果的随机性比较小,不容易过拟合,使得最后模型的预测更加稳定。

  • 关于XGBoost的详细论述可参考本专题的详述XGBoost。

总结:

  1. Adaboost与GBDT两者boosting的不同策略是两者的本质区别。

  2. Adaboost强调Adaptive(自适应),通过不断修改样本权重(增大分错样本权重,降低分对样本权重),不断加入弱分类器进行boosting。

  3. 而GBDT则是旨在不断减少残差(回归),通过不断加入新的树旨在在残差减少(负梯度)的方向上建立一个新的模型。——即损失函数是旨在最快速度降低残差。

  4. 而XGBoost的boosting策略则与GBDT类似,区别在于GBDT旨在通过不断加入新的树最快速度降低残差,而XGBoost则可以人为定义损失函数(可以是最小平方差、logistic loss function、hinge loss function或者人为定义的loss function),只需要知道该loss function对参数的一阶、二阶导数便可以进行boosting,其进一步增大了模型的泛华能力,其贪婪法寻找添加树的结构以及loss function中的损失函数与正则项等一系列策略也使得XGBoost比传统的GBDT算法更快速高效。

  5. XGBoost的具体策略可参考本专栏的XGBoost详述。
    GBDT每一次的计算是都为了减少上一次的残差,进而在残差减少(负梯度)的方向上建立一个新的模型。利用绝对值损失函数的负梯度来作为损失函数的近似值,而XGBoost则利用了损失函数的一阶、二阶梯度,结合泰勒展开,求出损失函数的近似值。

  6. 传统GBDT以CART作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)

  7. 传统GBDT在优化时只用到一阶导数信息,xgboost则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数。顺便提一下,xgboost工具支持自定义代价函数,只要函数可一阶和二阶求导。

  8. xgboost在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和。从Bias-variance tradeoff角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,防止过拟合,这也是xgboost优于传统GBDT的一个特性。
  9. Shrinkage(缩减),相当于学习速率(xgboost中的eta)。xgboost在进行完一次迭代后,会将叶子节点的权重乘上该系数,主要是为了削弱每棵树的影响,让后面有更大的学习空间。实际应用中,一般把eta设置得小一点,然后迭代次数设置得大一点。(补充:传统GBDT的实现也有学习速率)
  10. 列抽样(column subsampling)。xgboost借鉴了随机森林的做法,支持列抽样,不仅能降低过拟合,还能减少计算,这也是xgboost异于传统gbdt的一个特性。对缺失值的处理。对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向。
  11. xgboost工具支持并行。boosting不是一种串行的结构吗?怎么并行的?注意xgboost的并行不是tree粒度的并行,xgboost也是一次迭代完才能进行下一次迭代的(第t次迭代的代价函数里包含了前面t-1次迭代的预测值)。xgboost的并行是在特征粒度上的。我们知道,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),xgboost在训练之前,预先对数据进行了排序,然后保存为block结构,后面的迭代中重复地使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。
  12. 可并行的近似直方图算法。树节点在进行分裂时,我们需要计算每个特征的每个分割点对应的增益,即用贪心法枚举所有可能的分割点。当数据无法一次载入内存或者在分布式情况下,贪心算法效率就会变得很低,所以xgboost还提出了一种可并行的近似直方图算法,用于高效地生成候选的分割点。
  13. GBDT采用的是数值优化的思维, 用的最速下降法去求解Loss Function的最优解, 其中用CART决策树去拟合负梯度, 用牛顿法求步长.XGboost用的解析的思维, 对Loss Function展开到二阶近似, 求得解析解, 用解析解作为Gain来建立决策树, 使得Loss Function最优.

猜你喜欢

转载自blog.csdn.net/Dby_freedom/article/details/81975255
今日推荐