在上一篇《XGBoost源码阅读笔记(1)--代码逻辑结构》中向大家介绍了XGBoost源码的逻辑结构,同时也简单介绍了XGBoost的基本情况。本篇将继续向大家介绍XGBoost源码是如何构造一颗回归树,不过在分析源码之前,还是有必要先和大家一起推导下XGBoost的目标函数。本次推导过程公式截图主要摘抄于陈天奇的论文《XGBoost:A Scalable Tree Boosting System》。在后续的源码分析中,会省略一些与本篇无关的代码,如并行化,多线程。
一、目标函数优化
XGBoost和以往的GBT(Gradient Boost Tree)不同之一在于其将目标函数进行了二阶泰勒展开,在模型训练过程中使用了二阶导数加快其模型收敛速度。与此同时,为了防止模型过拟合其给目标函数加上了控制模型结构的惩罚项。
图1-1 目标函数
目标函数主要有两部分组成。第一部分是表示模型的预测误差;第二部分是表示模型结构。
当模型预测误差越大,树的叶子个数越多,树的权重越大,目标函数就越大。我们的优化目标是使目标函数尽可能的小,这样在降低预测误差的同时也会减少树叶子的个数以及降低叶子权重。这也正符合机器学习中的“奥卡姆剃刀”原则,即选择与经验观察一致的最简单假设。
图1-1的目标函数由于存在以函数为参数的模型惩罚项导致其不能使用传统的方式进行优化,所以将其改写成如下形式
图1-2 改变形式的目标函数
图1-2与图1-1的区别在于图1-1是通过整个模型去优化函数,而图1-2的优化目标是每次迭代过程中构造一个使目标函数达到最小值的弱分类器,从这个过程中就可以看出图1-2使用的是贪婪算法。将图1-2中的预测误差项在处进行二阶泰勒展开:
图1-3 二阶泰勒展开
并省去常数项
图1-4 省去常数项
图1-4就是每次迭代过程中简化的目标函数。我们的目标是在第t次迭代过程中获得一个使目标函数达到最小值的最优弱分类器,即。在这里累加项n是样本实例的个数,为了使编码更加方便,定义一个新的变量表示表示叶子j的所有样本实例