本篇中我们结合XGBoost的论文《XGBoost: A Scalable Tree Boosting System》来理解一下该算法的原理。
这是一篇写自2016年的论文,当时已经有大量的竞赛、工作实践开始采用XGBoost。作者在论文中将XGBoost称为Scalable,正是基于它的高性能特点,据论文讲,根据当时的评估,在单机上的运行速度对比中,XGBoost较业内其它算法快了至少10倍以上。
论文核心思想导读
看论文的过程中可以结合以下两个资料:
https://xgboost.readthedocs.io/en/latest/tutorials/model.html,
https://homes.cs.washington.edu/~tqchen/pdf/BoostedTree.pdf
因为论文是高度精简的,有些推导过程是直接省略的,所以需要看一些补充材料。尤其是上面第二个PPT材料,讲得很有条理,也有推理的过程。
在正式阅读原文前,我们需要先在脑海里回顾一下一个普通的决策树构建过程中关键点有哪些,这样在读论文的过程中就可以有意识地进行对比它是怎么做的,在以后去看新的tree boosting方法时,也可以更有条理地去对比关键点。
- 定义损失函数,否则没办法判断决策树分裂后是变好还是变坏了
- 有了损失函数的定义后,怎样来找每个节点上使用哪个变量,以及该变量值的哪个数值点来进行分裂
- 如何判断是否可能存在过拟合,怎样剪枝
- 叶子节点上的值怎么使用
下面开始阅读论文《XGBoost: A Scalable Tree Boosting System》。我们这里无法面面俱到,更多是把一些作者话里放外省略掉的一些推导、想法进行展开讨论。方便大家在逻辑上推敲得更充分。所以可以结合其它讲XGBoost上的文章一起来看。
论文共分了几个核心部分:
- 如何用boosting的方法训练集成树
- 如果寻找分裂点
- 系统上的设计(并行、分布式)
- 数据实验
第一部分。
先来说用boosting的方法训练树。这里的核心是设计目标函数,并求解该函数。在XGBoost中,作者采用了如下的目标函数:
注意这里与普通的GBDT相比,多了一项对于叶子节点上得分值的平方和。其实正则化的设计是比较灵活的,不同的人可以有不同的方法,更多是基于经验原则来看是否有益于模型整体表现。作者在文中说加了这样一个设计可以使得叶子节点的得分值更加平滑,以避免过拟合。那么为什么呢?
下面是笔者的理解:
有没有严格的数学推理呢?根据柯西不等式定理,可以做如下推导:
由此可见,如果有多棵树满足了目标函数中真值与预测值的损失项,那么就看谁的正则化项更小了,其中T是树的叶子节点数量,叶子越少越好;得分平方和项则是不同叶子节点之间得分值越接近越好;至于为什么要这样设计,用作者的原话来说:
Of course, there is more than one way to define the complexity, but this one works well in practice.
暂时没有看到相关资料谈到如果不加后面这个对于得分平方和的正则化项,XGBoost会损失多少精度,所以只能猜测是作者在经验基础上的神来之笔。
第二部分。
接下来作者讲了如何做boosting的过程&