1. XGBOOST 回顾
这是一篇2015年陈天奇发表的文章,主要是大名鼎鼎的XGBOOST算法的介绍。XGBOOST广泛用于各种比赛和实际应用中,是非常实用的算法。XGBOOST是ensemble decision tree算法系列中的一个改进算法,与常规决策树(复习一下:最大化信息增益(ID3),信息增益率(C4.5)或GINI值(CART))中损失函数为不同,XGBOOST的损失函数不是计算ensemble中的每棵树的真实值与预测值的残差之和,而是在一棵树的残差之下进行继续的decision tree的计算。
首先回顾一下tree ensemble 模型。
假设数据集包含n个样本,每个样本有m个特征。一个包含了K个树的tree ensemble模型可以表示为:
其中
是回归树(CART)。这里表示每个树的对应的叶子index,T是每个树的叶子数量。每个
对应于一个独立的树结构q和叶子权重w。
Tree ensemble的损失函数为:
其中是可微凸函数,测量的是每个树的预测值与真实值的差别。
是正则项。
对于XGBOOST来说,损失函数为:
其中是第i个instance在第t次迭代的预测值,而xgboost会继续添加
函数来最小化loss function。从损失函数的角度来看,因为里面的参数包含函数,这不是一个传统方法可以优化的损失函数,因此Gradient Tree Boosting用的是一步步相加的办法。
这个损失函数可以进行泰勒二级展开:
定义,可以把损失函数进行变形:
经过一系列变换并展开正则项,最后可以把损失函数写成:
对于一个固定的结构,叶子j的最优的权重可以算出
带入损失函数后可以写作:
上式可以看作对于树结构的一个评估。对于boosting tree,我们一般从一个叶子开始,然后greedly增加分叉。假设左叉和右叉上的instances sets可以表示为和
。所以增加一个分叉损失函数降低的值可以计算为:
在grow tree的时候,一般还有一些方法可以减少过拟合,比如对feature也就是column进行下采样。另一种方法是shrinkage,即每长出一个树杈一个小于1的权重(一般是0.1)。
2. 本文的一些优化
2.1 分支点选取
一般的,有贪心的分支点选取,即对于一个新的叶子,遍历所有的feature和所有的数据,得到最优的分界点。然后数据量过大无法全部fit进缓存里时,这种贪心算法却没有办法有效的计算了。一种优化方法是根据特征的quantile作下采样,保证采样的样本跟原分布的是相似的,从而根据样本搜索的给出一些分支点的推荐,从而加快找到最优点。
2.2 Weighted Quantile Sketch
对于所有样本权重相同的一般的下采样,已经有算法(quantile sketch)来解决这个问题,但对于boosted tree的loss function,可以发现这是个带权重的下采样,每个样本的权重是loss function的二次偏导。见下式:
XGboost也开发一套考虑了weight的distributed weighted quantile sketch algorithm来找下采样的样本集。
2.3 Sparsity-aware Split Finding
由于大多数的输入(X)都是稀疏矩阵,所以XGBOOST也考虑到了这个问题,对missing value做了default的归类。至于向哪个方向归类,则通过优化完成。结果表示,对于稀疏矩阵的特殊处理,及大的提高了计算效率。
3. 系统设计
3.1 Block system
对于寻找split point,由于需要sort每个feature,所以可以把feature sort好以后按CSC format存储在内存里,下次直接调用,这些内存单元叫block。 对于贪心算法,所有数据存在一个block里,下次计算的时候复杂度只是线性搜索,而这种方法也可以帮助近似算法。可以把不同的行存在不同的block中,并行调用。具体可见下图:
3.2 Cache Aware
这里没太明白,似乎是csc按列存储的数据,在计算时由于要算score,需要按行抽取数据,结果造成了不连续的memory access. "This slows down split finnding when the gradient statistics do not fit into CPU cache and cache miss occur."
对于贪心算法,作者通过增加一个线程来抽取梯度的统计值,然后用mini batch的方法来计算累加。
对于近似算法,通过控制block的大小。具体可见图4.
3.3 Blocks for Out-of-core Computation
这里有两点优化:block compression和block sharding。一方面,利用CSC压缩数据,然后在用的时候利用额外的线程解压。另一方面,用不同的磁盘来存数据,并用额外的线程来分别调用,减少IO瓶颈。
4 xboost评估和个人总结
作者总结了各个系统里关于tree boosting的实现情况,其中xgboost是最全面的。作者又在几个领域的公开数据集里用XGBOOST的效率做了验证,证明了XGBOOST的性能显著好于其他的tree boosting的实现。
在实现一个算法的时候,不仅要考虑算法的准确性,还要考虑算法在大规模数据集上的实现效率。本文中的几种加速方法都很值得借鉴,包括做近似计算,列存储,压缩,分布式,缓存等等。
5 Reference
[1]T. Chen和C. Guestrin, 《XGBoost: A Scalable Tree Boosting System》, Proceedings of the 22nd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining - KDD 2016, San Francisco, California, USA, 2016, 页 785–794.