XGBoost-原理推导(中):从目标函数到最优切分点

张开发
2026/4/10 21:17:12 15 分钟阅读

分享文章

XGBoost-原理推导(中):从目标函数到最优切分点
1. 目标函数XGBoost的核心优化逻辑XGBoost之所以能在各类机器学习竞赛中屡获佳绩关键在于它对目标函数的精妙设计。这个目标函数由两部分组成衡量预测偏差的损失函数和控制模型复杂度的正则项。就像考试既要追求高分降低偏差又要避免熬夜复习控制复杂度两者需要平衡。具体来看对于包含n个样本的数据集第t轮迭代时的目标函数可以表示为Obj(t) ∑[L(y_i, ŷ_i^(t-1) f_t(x_i))] Ω(f_t)其中L是损失函数如均方误差ŷ_i^(t-1)是前t-1轮的预测结果f_t是本轮要学习的树模型Ω(f_t)则是正则化项。这里有个精妙的处理通过泰勒展开将目标函数近似为二阶可导形式。假设我们用平方损失函数其一阶导g_i 2(ŷ_i^(t-1) - y_i)二阶导h_i 2。这意味着XGBoost实际上是在用牛顿法进行优化比传统梯度下降收敛更快。2. 决策树的正则化艺术决策树作为基学习器时XGBoost的正则化设计尤为精巧。不同于简单地限制树深度它从两个维度控制复杂度叶子节点数量T相当于控制模型宽度叶子权重w的L2范数防止单个节点过度影响预测具体正则项表达式为Ω(f_t) γT 0.5λ∑(w_j^2)γ和λ都是可调超参数。实践中我发现设置γ0.1λ1通常能取得不错的效果但具体值需要交叉验证。这种设计带来一个好处算法会自动倾向于选择分裂后增益足够大的节点。我曾在客户流失预测项目中测试过当γ设为0.3时模型平均深度比默认值减少了2层但AUC仅下降0.005显著提升了线上推理速度。3. 结构分数连接树结构与模型效果经过一系列推导我们可以得到简化后的目标函数Obj(t) -0.5∑(G_j^2/(H_jλ)) γT其中G_j和H_j分别是叶子j上所有样本的一阶导和二阶导之和。这个结果非常有意思——树的结构好坏可以直接用数值量化评估。在实际编码时我们会预先计算每个样本的g_i和h_i。以Python为例def get_gradients(y_true, y_pred): # 以平方损失为例 return 2*(y_pred - y_true), np.full_like(y_true, 2)4. 寻找最优切分点的两种策略4.1 精确贪心算法这是最直接的分裂方法步骤如下对当前节点所有样本按特征值排序遍历所有可能的分裂点计算分裂后的增益gain 0.5*[GL^2/(HLλ) GR^2/(HRλ) - (GLGR)^2/(HLHRλ)] - γ选择增益最大的分裂方案我在实践中发现几个优化点对连续特征可以先做分桶处理对类别型特征采用直方图算法设置min_child_weight参数防止过拟合4.2 近似算法当数据量超过内存大小时精确算法就不适用了。XGBoost提供了两种近似策略Global模式在建树前全局生成候选切分点Local模式每次分裂时重新生成候选点在开源实现中可以通过设置tree_methodapprox来启用。有个经验之谈当特征维度超过100时使用max_bin64能在精度和速度间取得不错平衡。5. 加权分位数与稀疏感知XGBoost有两个容易被忽视但极其重要的特性加权分位数草图用二阶导数h_i作为样本权重来选择候选分裂点。这意味着对预测不确定的样本h_i小会被赋予更低权重算法更关注预测确定性高的区域稀疏感知算法自动学习缺失值的最佳处理方向。在医疗数据等缺失值常见的场景特别有用。实现上是通过# 在节点分裂时 if feature_missing: default_direction get_best_direction()我曾经处理过一个金融风控数据集其中30%的特征存在缺失。启用enable_sparseTrue后模型训练时间缩短了40%且KS指标提升了5%。

更多文章