本文包含
- xgboost的整体训练过程
- 每次迭代,树的生成过程
- 叶子分裂过程做详尽的公式说明
本文不包含
- xgboost在实现上的并行计算优化(感兴趣的可以一起阅读源码交流)
gbdt是一种boosting方式集成弱学习器的模型,这里的弱学习器是CART, xgboost基于gbdt进行了改进,使得这种boosting算法在模型的预估效果上和训练的效率上都得到了提升。
一、整体训练过程:
- 算法在拟合的每一轮都生成一棵树
- 在拟合这个树之前需要计算损失函数在每一个样本上的一阶导数和二阶导数
- 贪心策略生成当前这一轮的树结构
- 知道了树结构后就知道每个叶子节点有哪些样本,可以得到该叶子节点上所有样本的一阶导数和(G表示)
- 计算每个叶子节点的预估值
- 当前树的预估结果➕前面预估结果,完成对模型的纠偏
假设总共训练了k轮,那么每个样本的最终预估结果是之前所有树预估结果的和。
二、How to 生成一棵树
因为树的结构千千万,所以一般用贪心策略来优化:
a、从深度为0的树开始,对每个叶节点枚举所有的可用特征
b、 针对每个特征,把属于该节点的训练样本根据该特征值升序排列,通过线性扫描的方式来决定该特征的最佳分裂点,并记录该特征的最大收益(采用最佳分裂点时的收益)
c、 选择收益最大的特征作为分裂特征,用该特征的最佳分裂点作为分裂位置,把该节点生长出左右两个新的叶节点,并为每个新节点关联对应的样本集
d、递归执行到满足特定条件为止
本文主要分析回归模型的情况(xgbost用于分类和回归训练过程基本一致,主要在于损失函数不一样。如果读者有要求,我再展开讨论。),回归问题也可以有很多损失函数进行选择,如平方损失,绝对损失和huber损失等等。这里讨论平方损失的情况。
如果树的结构是固定的,那么我们已经知道了每个叶子结点有哪些样本,所以每个叶子的一阶导数和G和二阶导数和H是确定的,但每个叶子的预估值不确定,那么令目标函数一阶导为0,则可以求得叶子结点对应的值
到现在,对于如何生成一颗CART树,应该就非常清楚了。关键在于O(data*features)时间复杂度下计算每一次的信息增益Gain(a),以及在确认树结构后,如何快速的计算每个叶子节点的预估值(每个叶子节点中的样本预估值相同),即每个样本在这棵树下的预估值。
本人才疏学浅,若有出入,烦请不吝赐教。蟹蟹~
参考: