Prerequisite: CART回归树
CART回归树是假设树为二叉树,通过不断将特征进行分裂。比如当前树结点是基于第j个特征值进行分裂的,设该特征值小于s的样本划分为左子树,大于s的样本划分为右子树。
而CART回归树实质上就是在该特征维度对样本空间进行划分, 而这种空间划分的优化是一种NP难问题,因此在决策树模型中是使用启发式方法解决。典型CART回归树产生的目标函数为:
当我们为了求解最优的切分特征j和最优的切分点s,就转化为求解这么一个目标函数:
XGBoost数学原理推导
该算法思想就是不断地添加树,不断地进行特征分裂来生长一棵树,每次添加一个树,其实是学习一个新函数,去拟合上次预测的残差。当我们训练完成得到k棵树,我们要预测一个样本的分数,其实就是根据这个样本的特征,在每棵树中会落到对应的一个叶子节点,每个叶子节点就对应一个分数,最后只需要将每棵树对应的分数加起来就是该样本的预测值。
如下图例子,训练出了2棵决策树,小孩的预测分数就是两棵树中小孩所落到的结点的分数相加。爷爷的预测分数同理。
爷爷的预测分数
XGBoost考虑正则化项,目标函数定义如下:
很显然,
代表损失函数, 而
代表正则化项
其中
为预测输出,
为label值,
为第k树模型,
为树叶子节点数,
为叶子权重值,
为叶子树惩罚正则项,具有剪枝作用,
为叶子权重惩罚正则项,防止过拟合。XGBoost也支持一阶正则化,容易优化叶子节点权重为0,不过不常用。
是叶子节点q的分数,
是叶子节点的编号,
是其中一颗回归树。也就是说对于任意一个样本
, 其最后会落在树的某个叶子节点上, 其值为
正如上文所说,新生成的树是要拟合上次预测的残差的,即当生成t棵树后,预测分数可以写成:
同时,可以将目标函数改写成(其中
代表当前树上某个叶子节点上的值):
很明显,我们接下来就是要去找到一个
能够最小化目标函数。XGBoost的想法是利用其在
处的
展开近似它。所以,目标函数近似为:
其中
为一阶导数,
为二阶导数, 其中
前面的
为泰勒二阶展开后的二阶导的系数
:
为什么此处可以用二阶导呢?
首先我们需要明确一个概念, 我们的boosting每一轮迭代是在优化什么呢? 换句话说我们在用损失函数
在干什么呢? 其实我们看Boosting的框架, 无论是GBDT还是Adaboost, 其在每一轮迭代中, 根本没有理会损失函数具体是什么, 仅仅用到了损失函数的一阶导数。仅仅用一阶导数的问题就是, 我们根本无法保证我们找到的是全局最优。除非问题本身
是强凸的 (convex)而且最好是smooth的。每次迭代相当于就是最优化负梯度。即下式中的
, 因为是负梯度所以前面要加负号,
代表学习率。
有没有感觉这个公式形式很熟悉, 是不是就是一般常见的linear regression 的 stochastic 梯度更新公式。既然GBDT用的是Stochastic Gradient Descent, 我们回想一下, 是不是还有别的梯度更新的方式, 这时, 牛顿法 Newton's method就出现了。可以说, XGBoost是用了牛顿法进行的梯度更新。
我们先来看一下泰勒展开式:
而对于上面这个公式值, 其与
之间的误差, 可以用如下公式表示:
我们保留二阶泰勒展开:
这个式子是成立的, 当且仅当
趋近于0, 我们对上式求导 (对
求导) 并令导数为0。
即得到:
所以得出迭代公式:
将损失函数与
对应起来:
所以实际上 x 即为
,而
即为
。
,故根据二阶泰勒展开,
可以表示为:
用
替代上式中的
, 即可得到 (此处的
就是上面的
, 不同写法而已):
这里有必要再明确一下,
和
的含义。gi怎么理解呢?假设现有
棵树, 这
棵树组成的模型对第i个训练样本有一个预测值
。 这个
与第i个样本的真实标签
肯定有差距, 这个差距可以用