XGBoost基本原理

XGBoost的实现,我以为主要仍是在于对GBDT的改良上。对于GBDT仍是不太熟悉的朋友,请看我这一篇文章《GBDT》。我我的认为这二者区别主要仍是在于细节上,理解了GBDT我认为就差很少等于理解了XGBoost。算法

我重点比较一下XGBoost与GBDT两种算法的不一样:机器学习

XGBoost的目标函数与GBDT存在泰勒展开项的不一样:

最基本的差距就在于XGBoost比GBDT多了两项泰勒展开式。具体这个泰勒展开式是怎么获得的,是对于什么展开的呢?咱们看:
XGBoost算法能够当作是由K棵树组成的加法模型:函数

XGBoost加法模型
XGBoost加法模型

其中F为全部树组成的函数空间(这里的回归树也就是一个分段函数,不一样分段的不一样取值就构成了一颗树),与通常机器学习算法不一样的是,加法模型不是学习d维空间的权重,而是直接学习决策树的集合。
上述加法模型的目标函数定义为:post

目标函数
目标函数

其中Ω表示决策树的复杂度,那么该如何定义树的复杂度呢?好比,能够考虑树的节点数量、树的深度或者叶子节点所对应的分数的L2范数等等。
如何来学习加法模型呢?
解这一优化问题,能够用前向分布算法(forward stagewise algorithm)。有了以前GBDT的基础,咱们知道,加法模型的学习器每次都用函数来拟合上一棵树没有拟合完整的残差,最后将这些残差所有加起来就会获得对于目标完整的预测,这也叫作Boosting。具体地,咱们从一个常量预测开始,每次学习一个新的函数,过程以下:
学习

加法学习器的Boosting
加法学习器的Boosting

这个公式看起来仍是比较拗口,想要理解的话建议看我以前的文章《GBDT》,了解了工做模式这公式就好理解了。优化

这就会产生一个新的问题,那个新加入的函数f到底怎么获得的呢?这个原则仍是最小化目标函数。咱们能够将咱们的目标函数写为:3d

目标函数变式
目标函数变式

咱们再用平方偏差来衡量咱们的损失函数:cdn

平方偏差衡量损失函数
平方偏差衡量损失函数

其中 就是咱们所谓的残差(residual)。咱们每一次使用平方函数的时候,算法都是为了拟合这个残差。
可能有的朋友对于泰勒公式不是很是熟悉,我将基本的泰勒公式用法写在这:blog

泰勒公式基本形式
泰勒公式基本形式

咱们都知道,泰勒级数展开实际上是有无穷多项的,在无穷多项形式里是严格等于,这里咱们暂且只取了前三项省略了后面,因此就是约等于。
那有了泰勒公式的基础,咱们将前面的目标函数变式能够转化为:递归

目标函数泰勒级数展开三项
目标函数泰勒级数展开三项

其中,g与h分别是损失函数的一阶偏导数和二阶偏导数,具体数学形式以下:

泰勒展开的一次微分项与二次微分项
泰勒展开的一次微分项与二次微分项

咱们也能够将常数项直接去掉,并不会影响,那就使得目标函数是这个样子:

去掉常数项的目标函数
去掉常数项的目标函数

因为要学习的函数仅仅依赖于目标函数,从“去掉常数项的目标函数”能够看出只需为学习任务定义好损失函数,并为每一个训练样本计算出损失函数的一阶导数和二阶导数,经过在训练样本集上最小化目标函数便可求得每步要学习的函数,从而根据加法模型可得最终要学习的模型。

GBDT的目标函数
GBDT的目标函数

就简单提一句GBDT与XGBoost的区别,明显能够看出,GBDT没有采用二次泰勒展开,这个看似很简单的区别,实际上带来更快的拟合,也大大缩减了生成树的规模,减小了运行时间。

XGBoost相比于GBDT加入了正则化项(Regularization)

咱们使用损失函数优化是为了不欠拟合,而使用正则化项就是为了不过拟合。正则化项与损失函数共同组成了咱们的目标函数。XGBoost比GBDT多添加了以树复杂度构成的正则化项,也是XGBoost实际表现更为优秀的缘由之一

何为正则化项?正则化项的做用是什么?
咱们都知道,咱们在优化目标函数的时候,老是但愿它更加的“小”,也就是优化通常是最小化的意思。如今咱们若是给目标函数加入一个变量的平方,那么若是这个变量一旦变大,那么目标函数为了“最小化”,必定很不喜欢这个变量变大的事实,选择的时候就会刻意避开会使变量变大的路径。这大概就是正则化的简单解释了。在XGBoost中,咱们是将树的复杂度做为正则项加入,那么优化器在工做的时候,会尽可能不让这个树更加复杂,也就达到咱们的效果。

咱们假设XGBoost决策树的叶子节点个数为T,该决策树是由全部叶子节点对应的值组成的向量w,以及一个把特征向量映射到叶子节点索引(Index)的函数 组成的,咱们将树能够写成:
,咱们也能够将决策树的复杂度定义成正则项:

决策树复杂度定义的正则化项
决策树复杂度定义的正则化项

则目标函数咱们能够写成:

完整正则项的目标函数
完整正则项的目标函数

用G与H代换一下原来的式子,咱们就获得了简化后的式子:

简化后的目标函数
简化后的目标函数

假设树的结构是固定的,即函数q(x)为固定的,令目标函数的一阶导数为0,则能够求出叶子节点j对应的值为:

叶子节点j对应的值
叶子节点j对应的值

因而在这种条件下,目标函数的值就变成了:

目标函数的值
目标函数的值

为何要计算这两个值呢?
是为了给你们描述单棵决策树的生成过程:

  1. 枚举全部可能的树的结构q
  2. 用目标函数值为每一个q计算对应的分数Obj,分数越小说明结构越好
  3. 根据上一步结果,找到分数最小的子节点,生成新的分支,并为每一个子节点计算预测值

XGBoost的分裂增益与GBDT的比较

树结构数量是无穷的,因此实际上咱们不可能枚举全部可能的树结构。一般状况下,咱们采用贪心策略来生成决策树的每一个节点。

咱们来看看这个贪心算法是怎么工做的:

  1. 从深度为0的树开始,对每一个叶节点枚举全部的可用特征
  2. 针对每一个特征,把属于该节点的训练样本根据该特征值升序排列,经过线性扫描的方式来决定该特征的最佳分裂点,并记录该特征的最大收益(采用最佳分裂点时的收益)
  3. 选择收益最大的特征做为分裂特征,用该特征的最佳分裂点做为分裂位置,把该节点生长出左右两个新的叶节点,并为每一个新节点关联对应的样本集
  4. 回到第1步,递归执行到知足特定条件为止

如何计算每次分裂的收益呢?假设当前节点记为C,分裂以后左孩子节点记为L,右孩子节点记为R,则该分裂得到的收益定义为当前节点的目标函数值减去左右两个孩子节点的目标函数值之和:Gain=ObjC-ObjL-ObjR,具体地,根据目标函数值公式可得:

XGBoost的增益
XGBoost的增益