1 论文简介
XGBoost的作者是曾在华盛顿大学研究机器学习的大牛陈天齐,XGBoost全称是eXtreme Gradient Boosting,从名称看XGBoost仍然是GBDT,在GBDT基础上优化和增强。XGBoost以出众的效率和较高的预测准确率在各大算法比赛中被广泛使用。这篇文章介绍了XGBoost这种可扩展、端到端的Boosting Tree的新算法。
文章先介绍了Boosting Tree在现在机器学习领域中非常出彩,而XGBoost作为一种先进的Boosting Tree,被各大比赛的选手们广泛使用。2015年的Kaggle和KDDCup中,所有top排名的队伍都使用XGBoost。
XGBoost成功背后的最重要因素是在所有情况下的可扩展性。XGBoost在单台机器上的运行速度比现有流行解决方案快十倍以上,可在分布式或内存有限的环境中扩展到数十亿个实例。XGBoost的可扩展性是由于几个重要的系统和算法优化。文章介绍了这些创新:一种新颖的稀疏数据感知算法,用于处理稀疏数据;一种合理的加权分位数略图(weighted quantile sketch)能够在近似学习中处理有权重特征的数据。论文还提出了缓存访问模式,数据压缩和分片的方法。通过结合这些方法,XGBoost可扩展、并行和分布式处理使学习速度更快,用比现有系统少得多的资源来处理数十亿规模的数据。
2 Boosting Tree简介
2.1 Boosting Tree正则化项优化
文章先简单介绍了Gradient Boosting Tree。使用k棵独立的回归树(CART)使用Boosting集成预测,F包含所有k棵树。
![873ce29a9ae31e498b4f1f90621495a9.png](https://i-blog.csdnimg.cn/blog_migrate/6ecf09eaa901e3299357b3120055cc4e.png)
![bb4db43fe68a3d2871da795b51495000.png](https://i-blog.csdnimg.cn/blog_migrate/2d2b9d69eac3dc39254de70154554790.png)
这里,q是映射到树叶子节点索引的函数,T是叶子节点数,w是叶子权重,连续值,也叫score,是映射到该节点的预测值。
下图是Boosting Tree集成学习的示例。tree1中,+2是预测男孩对游戏感兴趣的权重w1,tree2中,+0.9是对男孩的权重w2。最终预测结果是两棵树的score简单加和。
![11c1ac3be608d0905835c663f78ce59d.png](https://i-blog.csdnimg.cn/blog_migrate/82f8136de98d5348a24d9499ac0e396e.png)
下图是Boosting Tree的目标函数,前一项l是损失项,描述模型拟合训练数据的优劣,从训练数据预测有多好。后一项Ω是正则化项,Ω作为惩罚项减少模型复杂度,能平滑权重系数防止过拟合。这里
![d40cf67cd6fba2cb49d7dc569b7384fb.png](https://i-blog.csdnimg.cn/blog_migrate/433d9676aa2d7f85d97ef2c0a0eea946.png)
下图是Boosting tree目标函数的另一种写法。根据加法模型,
注意:这里
![bcf4d5dd17ac777e186942df2e339e07.png](https://i-blog.csdnimg.cn/blog_migrate/0f46f8d9163421bd0aa5c962c9ccf5ee.png)
这里用到了高数知识泰勒展开公式。
![9fca5d4f240fbba16c5b72f70e131dd5.png](https://i-blog.csdnimg.cn/blog_migrate/3e622b2a47c1eeef5f989a4635705e71.png)
根据泰勒二阶展开,g和h是损失函数的一阶和二阶导数。
![6d6c0f097cbae359befa9694513fbd8b.png](https://i-blog.csdnimg.cn/blog_migrate/7d4eea32612cdd6155285cb3d527960b.png)
![11954417bc0035fc9260911517cd4e7f.png](https://i-blog.csdnimg.cn/blog_migrate/363cc88c8e0ef94ad748ec47e013f63f.png)
对上式去掉常数项,这里t-1棵树的loss已经计算出来,可以作为常数项去除。(待进一步明确)
![48690b667009ab8fc38bf24f85791e64.png](https://i-blog.csdnimg.cn/blog_migrate/831d13168ff2dab0b9efc0db75f186a5.png)
使用公式(2)替换公式(3)中的惩罚项。
![a08b75dc9d6cc85aec09b6a6697e07bb.png](https://i-blog.csdnimg.cn/blog_migrate/640903359d086a7581e1b905a3f2cbaa.png)
目标函数现在是w的函数。对w求导求极值,令求导结果等于0。
![74279df0d1ea46b1043f9e17a5c106e9.png](https://i-blog.csdnimg.cn/blog_migrate/76d6be71a9083ee91b511d565962787a.png)
把公式(5)带回到公式(4),计算平方后合并同类项,
![8d84951d912afef9bff0f3fc5827059b.png](https://i-blog.csdnimg.cn/blog_migrate/e9d1b5aee153b732f44053c498f29e25.png)
目标函数(6)是score函数,可用来衡量树结构质量的优劣和预测的好坏。
可以穷举所有的树结构q,利用公式(6)计算每棵树score,利用公式(5)优化叶节点权重,求最小化权重w。但树是无限多的,不可能穷举。实际中使用贪心算法,从一个节点出发,分割后形成一棵树。分割点的选择使用下图公式Gain的计算来选择。
![9ead9c79f213115d424dfb6a200eebe1.png](https://i-blog.csdnimg.cn/blog_migrate/5b9dfaf70a9d5b465299689e875d226e.png)
HL左子树分数,HR右子树分数,第三项是不分割可以得到的分数。减第三项表示分割后比分割前变化量,
最后一项
公式(7)同上,是Gain的另一种写法。
![265c6ee088c54dbdcb92d90e7a5e8b9b.png](https://i-blog.csdnimg.cn/blog_migrate/a958efca78536d7300d0de71700e65ce.png)
2.2 Shrinkage和subsampling防止过拟合
除了正则化项,Boosting Tree还加入了两项技术防止过拟合。第一项Shrinkage类似于随机梯度下降的步长(学习率),shrinkage是每次tree boosting后增加的学习率权重,能减少个体的影响,为后续的tree boosting留下更多空间,防止在构建某棵树时过拟合。第二项subsampling类似于RF里的列抽样,除了防止过拟合,subsampling还能在后续章节提到的并行计算加速计算。
3 如何寻找分割点的算法
3.1 传统贪心算法(Basic Exact Greedy Algorithm)
传统贪心算法,遍历所有分割点,选择最优分割点。如果有2个特征组合,一共有4对取值,穷举后要计算4次才能选择最优分割点。
传统算法必须先对特征值排序,然后遍历数据计算梯度值。缺点就是效率差,数据可能都不能全放进内存。
3.2 近似算法(Approximate Algorithm)
近似算法和传统贪心算法遍历所有分割点的做法不同,根据特征分位数的分布情况,给出备选特征分割点的建议(proposal)。
近似算法建议有两种方法,
Global方法在建树前对所有候选特征做分割选择,给出建议。并且在下层子树构建时都用建树时同样的选择。Global全局考虑,所以需要更多的候选特征。
Local方法在每次分割后re-propose,是对global分割后的优化,local方法提出的重新优化分割更精确,在更深的子树上分割更精确。但Local需要的候选特征更少。
现有的近似算法中,可以直接使用梯度分位数统计信息,也可以使用其他如二分策略(binning strategy)。梯度分位数统计在后续章节的分布式计算表现出色,甚至可接近传统贪心算法的准确度。
3.3 加权分位数略图(weighted quantile sketch)
近似算法很重要的一步就是找到备选分割点。通常情况会均匀挑选一个特征的分位数作为候选。集合
![49fc5a7c2be51b92d28e18df0a7919b2.png](https://i-blog.csdnimg.cn/blog_migrate/c9420a8123a1917656ba23c7a985bd79.png)
![4d5b90aed17c23245ede070c948b2676.png](https://i-blog.csdnimg.cn/blog_migrate/12a37d3e2b1e41361a65bebc418e2e42.png)
对于每个分割点,其函数值
函数目标是找到一组候选的分割点
![c07d8c402a25f5f40727d911fe43ba83.png](https://i-blog.csdnimg.cn/blog_migrate/e6b343b3dc3ec2d49e328194996faff8.png)
直观上看,这大致表示总共选出1/ε个候选点。这里每一个点都按照其二阶导h进行加权。为了说明为何可以使用二阶导h作为权重,可以把等式3改写成如下形式。
![1b0d3f890f8dca526f9920576509f32d.png](https://i-blog.csdnimg.cn/blog_migrate/e6cc3e8974fb1fba4314d02a6553a18c.png)
即gi/hi做label时的L2损失平方乘以hi作为权重。
对于大规模数据集来说,很重要的是寻找符合条件的候选分割点。已有的分位数略图算法可以解决当样本权重相同时的问题。然而,还没有哪个现成的分位数略图算法可以解决权重不同的样本数据。因此,大多数近似算法使用随机抽样或启发式的方法,这些方法要不是有失败的可能,要不就是没有理论支撑。
为了解决这个问题,论文引入了一个新颖的,有理论支撑的分布式加权分位数略图算法,其大意是提出一个可以支持融合与剪枝操作的数据结构。而每一个合并与剪枝操作又能保证一定量级上的准确度。细节算法和证明见原论文中的链接。(待进一步阅读)
3.4 稀疏数据感知分割算法(Sparsity-aware Split Finding)
现实数据出现稀疏矩阵(Sparsity)非常普遍,比如存在缺失值,大量的0值,特征工程使用one hot encoding独热编码。因此,在每个树节点增加缺省方向,让算法知道当数据出现稀疏的情况,仍能快速准确分割。
如下图所示,红色是树节点的缺省方向,样本X2中性别是缺失值,根据缺省方向仍然可以被分割。
![2f25af7108f8ef97eeaa407173512fcc.png](https://i-blog.csdnimg.cn/blog_migrate/f3451b26dddf10dd50ecdbaf5d44c328.png)
确定缺省方向有两种方法,最优方法也是default使用的是,只收集非缺失值,从非缺失值数据的统计信息学习到最好的缺省方向。
和其他算法相比,XGBoost能很好处理稀疏数据,随着数据量复杂度线性增长。使用稀疏矩阵感知算法的XGBoost,在实验中比其他算法快50倍,
4 系统实现
4.1 块存储
数据按列排序后在内存中以块(block)存储
排序很费时间,因此数据按列排序后在内存中以块存储,块中数据按列排序后以列压缩(CSC)方式存储。所有样本数据在计算前只需做一次排序,后续迭代多次使用排序结果。
传统贪心算法里,把所有数据集存储在一个block里,分割时可对预先排序的数据线性查找。因此一次扫描获得的数据统计信息,可以在后续各级分支计算上多次使用。
下图描述了这个过程。
![5b852575d545cac791cabc1896b543c2.png](https://i-blog.csdnimg.cn/blog_migrate/c2b0ad25122abeb439933ab462f8bd71.png)
在近似算法中,块结构也非常有用。整个数据使用多个块,每个块是整个数据集的子集。多个块可以分布在多台机器上,也可以从内存放在磁盘上。块中预排序的数据,分位数的计算分割也可以线性扫描。Local propose可以很方便在一个分支上频繁的做优化建议,二分搜索(binary search)也可在合并算法上线性计算。
在并行分割搜索时,可并行为每列数据收集统计信息,更有效率。块结构也能在列抽样(subsampling)操作时很方便选取列数据。
传统贪心算法的复杂度是
近似算法中,二分查找算法的复杂度是
4.2 缓存访问机制
块结构方法简化了节点分割计算时的复杂度,但会频繁读取不连续内存里的行数据,内存不连续降低了节点分割计算的速度。
缓存访问机制能解决传统贪心算法里访问不连续内存数据的问题。先把梯度统计信息数据放在每个线程的缓存里,能直接在内存中读写,减少运行开销。
下图显示了在大数据量比较(10M)中,缓存访问机制比无缓存快2倍速度。值得注意的数据量1M时,缓存访问机制没有明显的速度提升。
![4aa2b90f80cac42388e8efe4919f5575.png](https://i-blog.csdnimg.cn/blog_migrate/0b7fabecb64423a926e6245bb3c6da97.jpeg)
近似算法里,调整合适的块结构大小能减少运行开销。如果选择太小的块结构不能充分发挥并行特性,太大的块结构可能使梯度统计信息不能装入cache,缓存无法命中。考虑这两种情况要选择合适的块大小。从下图两个数据集给出的实验结果,选择每个块中包括
![6012ff62ae8c9e440fd861adcf0c5690.png](https://i-blog.csdnimg.cn/blog_migrate/603c0131d529fd5f6419f771a64c775b.png)
![6eef1bc545937a5b13746d551f45f753.png](https://i-blog.csdnimg.cn/blog_migrate/578e49753ec080d664a476deab3779bb.png)
4.3 磁盘数据的块压缩和数据分片技术
当数据不能全部装入内存,数据以块存储在磁盘上。除了CPU和内存,也充分对磁盘读取进行优化。
主要有2个技术,块压缩技术对磁盘上的block按列做压缩。
数据分片技术,把数据分片到多个磁盘上,每个磁盘分别存储数据并读取到内存中。这两个技术都增加了磁盘吞吐量。
5 总结
论文读毕,深感作者考虑全面。
论文介绍XGBoost在目标函数设计上增加了L1和L2正则项,限制叶子节点数目,降低叶子权重。同时Shrinkage能降低步长,消除个别树过拟合,为后续树提升留出更多空间。
在算法设计上,论文提出近似算法,global全局考虑分割点,local细节优化global后的分割结果。加权分位数从分位数统计信息提升近似算法性能。缺省方向在实战中为稀疏数据树的分割提供帮助。
在系统实现上,XGBoost 提出了块结构,Cache存取,磁盘数据的压缩和分片技术。
综合看,XGBoost从CPU(算法设计),MEM(Cache),Disk(压缩和分片)各方面考虑,极尽优化之能。XGBoost既快又准,横扫各大比赛成为大杀器令人称道。
相关文献:
《XGBoost: A Scalable Tree Boosting System》 : Tianqi Chen, Carlos Guestrin
XGBoost Documentation