xgboost将梯度提升树方法带到了一个极致,在很多比赛上都是首选的算法,本文总结一下自己对xgboost的一些理解。关于xgboost在算法上的优化这里就不再介绍,网上有很多好的文章,百度一下就可以找到。
精确贪心算法
在单机版本下xgboost支持精确贪心算法,树学习方法最重要的点就是选择最优的分割点,关于精确就是将每个特征按特征值预排序,然后枚举所有特征上所有可能的分割,计算增益,然后选择增益最大的值作为分割点,由于这里需要遍历每个特征值,因此计算开销在数据量很大时非常大。也是建树过程中最耗时的地方。在xgboost中寻找最优切分点这步是可以并行的。
关于贪心算法我的理解是,从树的第一层开始,对每一个树节点,都进行分割为左子树和右子树,是一种按层生长(level-wise)的决策树生长策略。lightGBM在这里进行了改进,使用了带有深度限制的按叶子生长 (leaf-wise)算法。
近似算法
精确贪心算法确实很强大,但是当数据不能全部读入内存时,这种方法的效率并不高。在分布式处理时也会有同样的问题,因此,需要有一种近似算法。这里有兴趣的可以去看论文,我对这块算法处理并不了解。论文
正则化
陈天奇ppt中的这句话令我印象深刻,xgboost不仅在目标函数中加入了正则化项,而且在每个弱学习器前都加上了收缩率
ϵ
\epsilon
ϵ,为了防止过拟合。
y
(
t
)
=
y
(
t
−
1
)
+
ϵ
f
t
(
x
i
)
y^{(t)} = y^{(t-1)} + \epsilon f_t(x_i)
y(t)=y(t−1)+ϵft(xi)
稀疏值处理
- presence of missing values in the data;
- frequent zero entries in the statistics;
- artifacts of feature engineering such as one-hot encoding。
It is important to make the algorithm aware of the sparsity pattern in the data. In order to do so, we propose to add a default direction in each tree node, which is shown in Fig. 4.
当特征存在缺失值时,xgboost预先给每个节点都设置了一个默认方向,缺失值,会进入该方向。该方向如何产生呢?最好的默认方向肯定是从数据种学习得到的,先将缺失值先全部归入右子树,枚举所有存在的特征值寻找的最优分割节点,再将缺失值全部归入左子树,枚举所有存在的特征值寻找的最优分割节点。从而获得缺失值情况下,最优分割节点,作为该节点默认方向。
剪枝
回忆下 G a i n = G L 2 H L + γ + G R 2 H R + γ − ( G R + G L ) 2 H R + H L + γ − γ Gain = \frac{G_L^2}{H_L + \gamma} +\frac{G_R^2}{H_R + \gamma} - \frac{(G_R + G_L)^2}{H_R + H_L + \gamma} -\gamma Gain=HL+γGL2+HR+γGR2−HR+HL+γ(GR+GL)2−γ可以是负的,当训练损失减少小于 γ \gamma γ
-
早停(Pre-stopping ) 在最优分割点存在负增益时停止分割,该分割可能之后的分割有好处,给学习器带来了欠拟合的风险
-
后剪枝(Post-Prunning )让一棵树生长到最大深度,然后递归修剪掉所有负增益的叶子节点。一般情况下后剪枝欠拟合风险小,泛化能力强。
特征重要性
关于xgboost特征重要性可以参见这篇文章
xgboost特征重要性指标: weight, gain, cover
调参
关于xgboost调参可以参见这篇文章
XGBoost类库使用小结
小节
关于模型训练效率方面的优化,我并没有系统学习过数据结构和算法,这里也就不总结了。
[1] https://www.jianshu.com/p/2920c97e9e16
[2] https://www.cnblogs.com/pinard/p/11114748.html
[3] 周志华,机器学习[M]. 清华大学出版社 ,2016.
[4] https://arxiv.org/pdf/1603.02754.pdf