XGBoost 原理详解(二):目标函数、梯度、Hessian 与分裂增益推导
这篇文章集中回答三个问题:
- 从似然假设到经验风险
- 叶权闭式解和分裂增益
- 缺失、权重与约束如何进入目标
数据生成、缺失机制与防泄露特征工程
数据生成过程与损失函数的工作假设
平方损失的高斯似然解释要求在给定协变量后,误差满足零均值、同方差与适当的独立条件。独立同分布并非使用平方损失的逻辑必要条件,而是把负对数似然严格化为同权残差平方和的一组充分假设。二元分类的伯努利模型使用对数几率自然参数 zzz:
Yi∣Xi∼Bernoulli(pi),log (pi1−pi)=F(Xi). Y_i\mid\boldsymbol{X}_i\sim\operatorname{Bernoulli}(p_i), \qquad \log\!\left(\frac{p_i}{1-p_i}\right)=F(\boldsymbol{X}_i). Yi∣Xi∼Bernoulli(pi),log(1−pipi)=F(Xi).
计数目标可用条件泊松均值 μi=exp(F(Xi))\mu_i=\exp(F(\boldsymbol{X}_i))μi=exp(F(Xi)),但过度离散与零膨胀需要另行检验。Cox 部分似然把风险函数与基线风险分离,依赖比例风险与非信息性删失等条件;它不能当作普通逐样本独立损失直接套入第三章的叶权推导。不同目标的梯度和 Hessian 必须按其实际风险集重新计算。
MCAR、MAR 与 MNAR 的识别边界
令 Mk=1M_k=1Mk=1 表示第 kkk 个变量缺失。MCAR 要求 MkM_kMk 与完整数据独立;MAR 允许缺失概率依赖可观测变量;MNAR 则允许它在给定已观测变量后仍依赖未观测值。仅凭观测数据不能一般地验证 MAR 对 MNAR 的区分。对业务含义明确的缺失,应同时保留缺失指示、记录采集流程,并在时间外样本上比较“原生缺失路由”和“填补加指示”的性能及校准。
XGBoost 的稀疏感知切分在候选阈值扫描时对缺失样本分别尝试默认向左与向右,选择较优的方向。它学习的是与训练目标相关的默认路由,不是对缺失值的因果解释。若上线采集机制变化,曾经有用的默认方向也可能成为漂移来源[1]。
类别编码与时间顺序
原生类别支持要求明确类别类型与受支持的树方法;其分区搜索和序列化约束应以所用 XGBoost 版本文档为准[2]。频率编码不直接使用标签,却可能泄漏测试总体频数;目标编码使用标签,必须逐折或按时间隔离。对类别 ccc,平滑编码为
m^c=∑i:Xi=cyi+αμ^nc+α,α>0.\widehat{m}_c= \frac{\sum_{i:X_i=c}y_i+\alpha\widehat{\mu}}{n_c+\alpha}, \qquad \alpha>0. mc=nc+α∑i:Xi=cyi+αμ,α>0.
普通 OOF 编码使验证行只读取其他折的标签;时间任务还须保证第 iii 行只读取严格早于 iii 的标签。噪声注入可作为训练期正则化选项,但必须在 OOF 编码之后进行,且不能污染验证与测试编码。未知类别回退到训练折先验。
代码:折外与历史前缀目标编码的完整实现
"""Leakage-safe preprocessing and categorical encoding demonstrations."""
from __future__ import annotations
from typing import Tuple
import numpy as np
import pandas as pd
from sklearn.model_selection import KFold
def synthetic_mixed_table(seed: int = 11) -> Tuple[pd.DataFrame, np.ndarray]:
rng = np.random.default_rng(seed)
n = 600
category = rng.choice(["north", "south", "east", "west"], n)
amount = rng.lognormal(2.0, 0.6, n)
risk = -2.0 + 0.45 * (category == "west") + 0.35 * np.log1p(amount)
probability = np.exp(-np.logaddexp(0.0, -risk))
target = rng.binomial(1, probability).astype(int)
missing = rng.random(n) < np.where(category == "west", 0.18, 0.03)
amount[missing] = np.nan
return pd.DataFrame({"region": pd.Categorical(category), "amount": amount}), target
def oof_target_encoding(
category: pd.Series,
target: np.ndarray,
n_splits: int = 5,
smoothing: float = 20.0,
seed: int = 11,
) -> np.ndarray:
"""Each training row uses only labels from its complementary folds."""
values = category.astype("string").fillna("<missing>").reset_index(drop=True)
y = np.asarray(target, dtype=float).reshape(-1)
if len(values) != len(y) or not np.all(np.isfinite(y)):
raise ValueError("Category and finite target must have matching lengths.")
if n_splits < 2 or smoothing <= 0:
raise ValueError("Use at least two folds and positive smoothing.")
result = np.empty(len(y), dtype=float)
splitter = KFold(n_splits=n_splits, shuffle=True, random_state=seed)
for train_index, valid_index in splitter.split(values):
prior = float(np.mean(y[train_index]))
frame = pd.DataFrame({"key": values.iloc[train_index], "y": y[train_index]})
summary = frame.groupby("key", dropna=False)["y"].agg(["sum", "count"])
encoded = (summary["sum"] + smoothing * prior) / (summary["count"] + smoothing)
result[valid_index] = values.iloc[valid_index].map(encoded).fillna(prior).to_numpy()
return result
def past_only_target_encoding(
category: pd.Series,
target: np.ndarray,
smoothing: float = 20.0,
) -> np.ndarray:
"""Input must be sorted by event time; a row never sees its own or future label."""
values = category.astype("string").fillna("<missing>").reset_index(drop=True)
y = np.asarray(target, dtype=float).reshape(-1)
if len(values) != len(y) or smoothing <= 0:
raise ValueError("Invalid target length or smoothing.")
frame = pd.DataFrame({"key": values, "y": y})
cumulative_sum = frame.groupby("key", dropna=False)["y"].cumsum() - y
cumulative_count = frame.groupby("key", dropna=False).cumcount()
global_prior_sum = np.cumsum(y) - y
global_prior_count = np.arange(len(y))
prior = np.divide(
global_prior_sum,
np.maximum(global_prior_count, 1),
out=np.full(len(y), 0.5),
where=global_prior_count > 0,
)
return ((cumulative_sum + smoothing * prior) / (cumulative_count + smoothing)).to_numpy()
if __name__ == "__main__":
table, label = synthetic_mixed_table()
print("OOF mean", float(np.mean(oof_target_encoding(table["region"], label))))
print("past-only mean", float(np.mean(past_only_target_encoding(table["region"], label))))
数据协议的反例检查
应当用实体、时间、采集批次与标签成熟时间共同设计切分。对每一项派生特征记录最晚可用时点 tkavailablet_k^{\mathrm{available}}tkavailable;只有满足
tkavailable≤tidecision t_k^{\mathrm{available}}\leq t_i^{\mathrm{decision}} tkavailable≤tidecision
才能用于样本 iii 的决策。填补器、缩放器、编码器与特征选择器必须仅在对应训练折拟合。将全集统计量预先写回数据表再交叉验证,是最常见也最隐蔽的穿越路径。
阶段目标、二阶优化与结构搜索
符号、维度与条件
设训练集为
D={(xi,yi)}i=1n,xi∈Rd,yi∈R. \mathcal{D}= \left\{(\boldsymbol{x}_i,y_i)\right\}_{i=1}^{n}, \qquad \boldsymbol{x}_i\in\mathbb{R}^d, \qquad y_i\in\mathbb{R}. D={(xi,yi)}i=1n,xi∈Rd,yi∈R.
第 ttt 轮加入树 ft(x)=wq(x)f_t(\boldsymbol{x})=w_{q(\boldsymbol{x})}ft(x)=wq(x)。树结构 qqq 把样本映射到 TTT 个叶节点,叶权向量为 w∈RT\boldsymbol{w}\in\mathbb{R}^Tw∈RT。加法模型与结构正则项分别为
y^i(t)=y^i(t−1)+ft(xi),\widehat{y}_i^{(t)}=
\widehat{y}_i^{(t-1)}+f_t(\boldsymbol{x}_i),yi(t)=yi(t−1)+ft(xi),
Ω(ft)=γT+12λ∑j=1Twj2,γ≥0,λ≥0.\Omega(f_t)=
\gamma T+\frac{1}{2}\lambda\sum_{j=1}^{T}w_j^2,
\qquad
\gamma\geq 0,
\quad
\lambda\geq 0.
Ω(ft)=γT+21λj=1∑Twj2,γ≥0,λ≥0.
训练的精确阶段目标为
L(t)=∑i=1nℓ (yi,y^i(t−1)+ft(xi))+Ω(ft).\mathcal{L}^{(t)}= \sum_{i=1}^{n} \ell\!\left(y_i,\widehat{y}_i^{(t-1)}+f_t(\boldsymbol{x}_i)\right) +\Omega(f_t). L(t)=i=1∑nℓ(yi,yi(t−1)+ft(xi))+Ω(ft).
推导需要两个条件:损失关于当前预测至少二阶可微;叶内累计曲率满足 Hj+λ>0H_j+\lambda>0Hj+λ>0。前者允许局部二次近似,后者保证每个叶权子问题严格凸并拥有唯一极小点。
若希望进一步给出余项的数值上界,可假设第三阶导数在本轮更新覆盖的预测区间内存在且满足 ∣ϕi(3)(u)∣≤Mi|\phi_i^{(3)}(u)|\leq M_i∣ϕi(3)(u)∣≤Mi。此时拉格朗日余项满足
∣Ri,3∣≤Mi6∣ft(xi)∣3. |R_{i,3}| \leq \frac{M_i}{6}|f_t(\boldsymbol{x}_i)|^3. ∣Ri,3∣≤6Mi∣ft(xi)∣3.
这是一项局部充分条件,不能推出整座离散树结构空间的全局收敛。平方损失的三阶导数为零,其二次展开则恰好无余项;二元逻辑损失需要控制原始分数的局部范围。不要把“有二阶导数”误写成“所有步长都安全”。
表:核心对象及其维度。
| 对象 | 维度 | 含义 |
|---|---|---|
| X\boldsymbol{X}X | n×dn\times dn×d | 样本—特征矩阵 |
| g,h\boldsymbol{g},\boldsymbol{h}g,h | n×1n\times 1n×1 | 样本一阶梯度与对角二阶曲率 |
| w\boldsymbol{w}w | T×1T\times 1T×1 | 当前树的叶权 |
| A\boldsymbol{A}A | n×Tn\times Tn×T | 叶归属矩阵,Aij=I(q(xi)=j)A_{ij}=\mathbb{I}(q(\boldsymbol{x}_i)=j)Aij=I(q(xi)=j) |
| G,H\boldsymbol{G},\boldsymbol{H}G,H | T×1T\times 1T×1 | 叶内梯度与曲率之和 |
由归属矩阵可写出 f=Aw∈Rn\boldsymbol{f}=\boldsymbol{A}\boldsymbol{w}\in\mathbb{R}^nf=Aw∈Rn、G=ATg\boldsymbol{G}=\boldsymbol{A}^{\mathsf T}\boldsymbol{g}G=ATg 与 H=ATh\boldsymbol{H}=\boldsymbol{A}^{\mathsf T}\boldsymbol{h}H=ATh。维度检查不是礼仪,而是推导的第一道单元测试。
高斯似然与平方损失的对应
假设响应由加性高斯噪声产生:
yi=F(xi)+εi,εi∼i.i.d.N(0,σ2).y_i= F(\boldsymbol{x}_i)+\varepsilon_i, \qquad \varepsilon_i\overset{\text{i.i.d.}}{\sim}\mathcal{N}(0,\sigma^2). yi=F(xi)+εi,εi∼i.i.d.N(0,σ2).
条件密度为
p(yi∣xi,F)=12πσ2exp [−(yi−F(xi))22σ2].p(y_i\mid\boldsymbol{x}_i,F)= \frac{1}{\sqrt{2\pi\sigma^2}} \exp\!\left[ -\frac{\left(y_i-F(\boldsymbol{x}_i)\right)^2}{2\sigma^2} \right]. p(yi∣xi,F)=2πσ21exp[−2σ2(yi−F(xi))2].
独立性使联合似然成为各项乘积。取负对数,并逐项展开:
logp(y∣X,F)=−∑i=1nlogp(yi∣xi,F)=n2log(2πσ2)+12σ2∑i=1n(yi−F(xi))2.\log p(\boldsymbol{y}\mid\boldsymbol{X},F)= -\sum_{i=1}^{n}\log p(y_i\mid \boldsymbol{x}_i,F)= \frac{n}{2}\log(2\pi\sigma^2) +\frac{1}{2\sigma^2} \sum_{i=1}^{n}\left(y_i-F(\boldsymbol{x}_i)\right)^2. logp(y∣X,F)=−i=1∑nlogp(yi∣xi,F)=2nlog(2πσ2)+2σ21i=1∑n(yi−F(xi))2.
当 σ2\sigma^2σ2 固定时,第一项与 FFF 无关,第二项的正常数因子不改变极小点,于是最大似然估计与最小化平方误差等价。这个结论并非说现实噪声一定高斯,而是说选择平方损失,等于在决策层面接受了高斯、同方差与轻尾的工作假设。第五章的重尾破坏实验正是来收这张欠条。
叶权高斯先验与二次正则化
给定树结构 qqq,对每个叶权施加独立零均值高斯先验:
wj∼N(0,τ2). w_j\sim\mathcal{N}(0,\tau^2). wj∼N(0,τ2).
其负对数先验为
−logp(w∣q)=−∑j=1Tlogp(wj)=T2log(2πτ2)+12τ2∑j=1Twj2. -\log p(\boldsymbol{w}\mid q)= -\sum_{j=1}^{T}\log p(w_j)= \frac{T}{2}\log(2\pi\tau^2) +\frac{1}{2\tau^2}\sum_{j=1}^{T}w_j^2. −logp(w∣q)=−j=1∑Tlogp(wj)=2Tlog(2πτ2)+2τ21j=1∑Twj2.
将前述公式 与前述公式 相加得到负对数后验。若把数据项整体乘以 2σ22\sigma^22σ2,则二次惩罚的相对强度满足
λ∝σ2τ2. \lambda \propto \frac{\sigma^2}{\tau^2}. λ∝τ2σ2.
噪声越强或先验越确信叶权应靠近零,λ\lambdaλ 就应更大。γT\gamma TγT 还可被理解为对叶数的指数型复杂度先验:每多开一片叶子,都必须支付固定的拓扑价格。
阶段目标的二阶泰勒展开与余项
为缩短记号,令当前预测 ai=y^i(t−1)a_i=\widehat{y}_i^{(t-1)}ai=yi(t−1),当前树输出 bi=ft(xi)b_i=f_t(\boldsymbol{x}_i)bi=ft(xi),并定义单变量函数
ϕi(u)=ℓ(yi,u). \phi_i(u)=\ell(y_i,u). ϕi(u)=ℓ(yi,u).
在 u=aiu=a_iu=ai 处对 ϕi(ai+bi)\phi_i(a_i+b_i)ϕi(ai+bi) 使用带余项的二阶泰勒公式:
ϕi(ai+bi)=ϕi(ai)+ϕi′(ai)bi+12ϕi′′(ai)bi2+Ri,3,\phi_i(a_i+b_i)= \phi_i(a_i) +\phi_i'(a_i)b_i +\frac{1}{2}\phi_i''(a_i)b_i^2 +R_{i,3}, ϕi(ai+bi)=ϕi(ai)+ϕi′(ai)bi+21ϕi′′(ai)bi2+Ri,3,
其中,若三阶导数在邻域内存在,则存在位于 aia_iai 与 ai+bia_i+b_iai+bi 之间的 ξi\xi_iξi,使
Ri,3=16ϕi(3)(ξi)bi3. R_{i,3}= \frac{1}{6}\phi_i^{(3)}(\xi_i)b_i^3. Ri,3=61ϕi(3)(ξi)bi3.
定义

把展开式代回前述公式,忽略三阶余项,得到
L(t)≈∑i=1n[ℓ(yi,ai)+gibi+12hibi2]+Ω(ft)=∑i=1nℓ(yi,ai)⏟与当前树无关+∑i=1n[gift(xi)+12hift2(xi)]+Ω(ft). \mathcal{L}^{(t)}\approx \sum_{i=1}^{n} \left[ \ell(y_i,a_i)+g_ib_i+\frac{1}{2}h_ib_i^2 \right] +\Omega(f_t) \\= \underbrace{\sum_{i=1}^{n}\ell(y_i,a_i)}_{\text{与当前树无关}} +\sum_{i=1}^{n} \left[g_if_t(\boldsymbol{x}_i)+\frac{1}{2}h_if_t^2(\boldsymbol{x}_i)\right] +\Omega(f_t). L(t)≈i=1∑n[ℓ(yi,ai)+gibi+21hibi2]+Ω(ft)=与当前树无关i=1∑nℓ(yi,ai)+i=1∑n[gift(xi)+21hift2(xi)]+Ω(ft).
去掉与 ftf_tft 无关的常数项,定义可优化的近似目标
L~(t)=∑i=1n[gift(xi)+12hift2(xi)]+γT+12λ∑j=1Twj2. \widetilde{\mathcal{L}}^{(t)}= \sum_{i=1}^{n} \left[g_if_t(\boldsymbol{x}_i)+\frac{1}{2}h_if_t^2(\boldsymbol{x}_i)\right] +\gamma T +\frac{1}{2}\lambda\sum_{j=1}^{T}w_j^2. L(t)=i=1∑n[gift(xi)+21hift2(xi)]+γT+21λj=1∑Twj2.
这一步好比给近视眼木匠配备曲率放大镜:一阶梯度告诉他木板往哪边歪,二阶曲率告诉他该削一毫米还是一厘米。但放大镜只在局部可靠,因此仍需学习率 η\etaη 控制实际步幅。
叶节点统计量聚合与最优叶权
令第 jjj 个叶中的样本索引集合为
Ij={i:q(xi)=j}. I_j=\left\{i:q(\boldsymbol{x}_i)=j\right\}. Ij={i:q(xi)=j}.
由于 ft(xi)=wjf_t(\boldsymbol{x}_i)=w_jft(xi)=wj 对所有 i∈Iji\in I_ji∈Ij 成立,前述公式 可重排为
L~(t)=∑j=1T[∑i∈Ijgiwj+12∑i∈Ijhiwj2]+γT+12λ∑j=1Twj2=∑j=1T[Gjwj+12(Hj+λ)wj2]+γT, \widetilde{\mathcal{L}}^{(t)}= \sum_{j=1}^{T} \left[ \sum_{i\in I_j}g_iw_j +\frac{1}{2}\sum_{i\in I_j}h_iw_j^2 \right] +\gamma T +\frac{1}{2}\lambda\sum_{j=1}^{T}w_j^2 \\= \sum_{j=1}^{T} \left[ G_jw_j +\frac{1}{2}(H_j+\lambda)w_j^2 \right] +\gamma T, L(t)=j=1∑Ti∈Ij∑giwj+21i∈Ij∑hiwj2+γT+21λj=1∑Twj2=j=1∑T[Gjwj+21(Hj+λ)wj2]+γT,
其中
Gj=∑i∈Ijgi,Hj=∑i∈Ijhi. G_j=\sum_{i\in I_j}g_i, \qquad H_j=\sum_{i\in I_j}h_i. Gj=i∈Ij∑gi,Hj=i∈Ij∑hi.
固定树结构后,各叶子彼此解耦。对第 jjj 项配方:
Gjwj+12(Hj+λ)wj2=12(Hj+λ)[wj2+2GjHj+λwj]=12(Hj+λ)(wj+GjHj+λ)2−12Gj2Hj+λ. G_jw_j+\frac{1}{2}(H_j+\lambda)w_j^2= \frac{1}{2}(H_j+\lambda) \left[ w_j^2+2\frac{G_j}{H_j+\lambda}w_j \right] \\= \frac{1}{2}(H_j+\lambda) \left(w_j+\frac{G_j}{H_j+\lambda}\right)^2 -\frac{1}{2}\frac{G_j^2}{H_j+\lambda}. Gjwj+21(Hj+λ)wj2=21(Hj+λ)[wj2+2Hj+λGjwj]=21(Hj+λ)(wj+Hj+λGj)2−21Hj+λGj2.
因为 Hj+λ>0H_j+\lambda>0Hj+λ>0,平方项非负,且仅当
wj∗=−GjHj+λ \boxed{ w_j^*= -\frac{G_j}{H_j+\lambda} } wj∗=−Hj+λGj
时取零。因此前述公式 是唯一全局极小点,而不只是驻点。也可通过求导复核:
∂L~(t)∂wj=Gj+(Hj+λ)wj,∂2L~(t)∂wj2=Hj+λ>0. \frac{\partial\widetilde{\mathcal{L}}^{(t)}}{\partial w_j}=G_j+(H_j+\lambda)w_j, \\ \frac{\partial^2\widetilde{\mathcal{L}}^{(t)}}{\partial w_j^2}=H_j+\lambda>0. ∂wj∂L(t)=Gj+(Hj+λ)wj,∂wj2∂2L(t)=Hj+λ>0.
结构评分与分裂增益的目标差分
把最优叶权代回前述公式,平方项消失,得到固定结构 qqq 的最优近似目标值:
Score(q)=−12∑j=1TGj2Hj+λ+γT. \boxed{ \operatorname{Score}(q)= -\frac{1}{2} \sum_{j=1}^{T} \frac{G_j^2}{H_j+\lambda} +\gamma T }. Score(q)=−21j=1∑THj+λGj2+γT.
分数越小越好。现在考虑把一个父叶 III 分成左右子叶 ILI_LIL 与 IRI_RIR。记
G=GL+GR,H=HL+HR. G=G_L+G_R, \qquad H=H_L+H_R. G=GL+GR,H=HL+HR.
分裂前,该局部结构对最优目标的贡献为
Sbefore=−12G2H+λ+γ. S_{\mathrm{before}}= -\frac{1}{2}\frac{G^2}{H+\lambda}+\gamma. Sbefore=−21H+λG2+γ.
分裂后,叶数增加一,局部贡献为
Safter=−12[GL2HL+λ+GR2HR+λ]+2γ. S_{\mathrm{after}}= -\frac{1}{2} \left[ \frac{G_L^2}{H_L+\lambda} +\frac{G_R^2}{H_R+\lambda} \right] +2\gamma. Safter=−21[HL+λGL2+HR+λGR2]+2γ.
把“旧目标减新目标”定义为收益,逐项相减:
KaTeX parse error: Expected 'EOF', got '&' at position 22: …atorname{Gain} &̲= S_{\mathrm{be…
只有当 Gain>0\operatorname{Gain}>0Gain>0 时,这次切分在二阶近似下才真正降低了正则化目标。Gain 不是神秘的经验分数,而是“分裂前后最优局部能量之差”。
结构复杂度惩罚与叶权阻尼
γ\gammaγ 与 λ\lambdaλ 作用在不同对象上。γ\gammaγ 按叶计费,改变树的拓扑;λ\lambdaλ 按权重幅度计费,改变固定拓扑上的动力学。
叶数惩罚与后剪枝判据
贪心生长时可以先允许候选切分展开,再自底向上检查收益。若某分支带来的累计收益不能覆盖 γ\gammaγ,便删除该分支。这是一种离散拓扑后剪枝:它不是把叶权缩小,而是让某些叶节点从结构上消失。γ\gammaγ 越大,模型越要求每次拓扑扩张提供可审计的能量回报。
二次正则与 Hessian 谱下界
对固定结构,叶权 Hessian 为对角矩阵
K=diag(H1,…,HT)+λIT. \boldsymbol{K}= \operatorname{diag}(H_1,\ldots,H_T)+\lambda\boldsymbol{I}_T. K=diag(H1,…,HT)+λIT.
其特征值为 Hj+λH_j+\lambdaHj+λ。若所有 Hj≥0H_j\geq 0Hj≥0,则最小特征值至少为 λ\lambdaλ;当 λ>0\lambda>0λ>0 时,即使某叶曲率接近零,子问题仍保持强凸。谱条件数为
κ(K)=maxj(Hj+λ)minj(Hj+λ). \kappa(\boldsymbol{K})= \frac{\max_j(H_j+\lambda)}{\min_j(H_j+\lambda)}. κ(K)=minj(Hj+λ)maxj(Hj+λ).
在分母很小时加入 λ\lambdaλ 通常会改善条件数,也直接缩小前述公式 的幅度。因此 λ\lambdaλ 同时是统计收缩器、数值阻尼器与局部信任机制。
一阶与二阶参数递推
若把叶权当作连续参数,固定结构下的二次近似可写为
Q(w)=GTw+12wTKw+γT. Q(\boldsymbol{w})= \boldsymbol{G}^{\mathsf T}\boldsymbol{w} +\frac{1}{2}\boldsymbol{w}^{\mathsf T}\boldsymbol{K}\boldsymbol{w} +\gamma T. Q(w)=GTw+21wTKw+γT.
一阶梯度下降递推为
w(k+1)=w(k)−αk(G+Kw(k)), \boldsymbol{w}^{(k+1)}= \boldsymbol{w}^{(k)} -\alpha_k \left(\boldsymbol{G}+\boldsymbol{K}\boldsymbol{w}^{(k)}\right), w(k+1)=w(k)−αk(G+Kw(k)),
其中步长 αk>0\alpha_k>0αk>0。二阶 Newton 递推为
w(k+1)=w(k)−K−1(G+Kw(k))=−K−1G. \boldsymbol{w}^{(k+1)}= \boldsymbol{w}^{(k)} -\boldsymbol{K}^{-1} \left(\boldsymbol{G}+\boldsymbol{K}\boldsymbol{w}^{(k)}\right) \\= -\boldsymbol{K}^{-1}\boldsymbol{G}. w(k+1)=w(k)−K−1(G+Kw(k))=−K−1G.
由于 QQQ 恰为二次函数,Newton 法一步到达最优点;其第 jjj 个分量正是前述公式。XGBoost 的巧妙之处,在于它没有对全部历史树的所有参数做一次巨型 Newton 更新,而是在每轮新增树上构造一个可分解、可贪心搜索的局部二阶子问题。
典型损失的梯度与 Hessian
平方损失
取
ℓ(y,y^)=12(y^−y)2, \ell(y,\widehat{y})= \frac{1}{2}(\widehat{y}-y)^2, ℓ(y,y)=21(y−y)2,
则
g=y^−y,h=1. g=\widehat{y}-y, \qquad h=1. g=y−y,h=1.
因此回归时叶节点的 HjH_jHj 就是叶内样本数。最小叶权曲率约束在此等价于最小叶样本量约束。
二元逻辑损失
令原始分数为 zzz,概率为
p=11+exp(−z), p= \frac{1}{1+\exp(-z)}, p=1+exp(−z)1,
负对数似然为
ℓ(y,z)=−ylogp−(1−y)log(1−p). \ell(y,z)= -y\log p-(1-y)\log(1-p). ℓ(y,z)=−ylogp−(1−y)log(1−p).
逐步求导可得
∂p∂z=p(1−p), \frac{\partial p}{\partial z}= p(1-p), ∂z∂p=p(1−p),
以及
g=∂ℓ∂z=p−y,h=∂2ℓ∂z2=p(1−p). g= \frac{\partial\ell}{\partial z} =p-y, \\ h= \frac{\partial^2\ell}{\partial z^2} =p(1-p). g=∂z∂ℓ=p−y,h=∂z2∂2ℓ=p(1−p).
当 ppp 极接近零或一时,hhh 接近零,Newton 步可能放大。min_child_weight、λ\lambdaλ、最大叶权限制与学习率共同构成安全带;数值实现还应使用稳定 sigmoid、概率截断与 Log-Sum-Exp。生产接口见第四章,纯 NumPy 白盒核见附录。
若将所有叶权作为参数,固定树结构时预测扰动为 Aw\boldsymbol{A}\boldsymbol{w}Aw,逻辑损失的二阶信息矩阵为
ATdiag (p1(1−p1),…,pn(1−pn))A+λIT. \boldsymbol{A}^{\mathsf T} \operatorname{diag}\!\left(p_1(1-p_1),\ldots,p_n(1-p_n)\right) \boldsymbol{A} +\lambda\boldsymbol{I}_T. ATdiag(p1(1−p1),…,pn(1−pn))A+λIT.
由于每个样本只属于一片叶,该矩阵为对角阵,第 jjj 个对角元恰为 Hj+λH_j+\lambdaHj+λ。伯努利自然参数下,pi(1−pi)p_i(1-p_i)pi(1−pi) 也是单个观测对原始分数的 Fisher 信息;这解释了为何极端概率样本对局部曲率预算贡献很小。这里讨论的是固定树结构的叶权坐标,不意味着树的离散切分空间拥有一个可微的全局黎曼度量。
这里 ∑i∈Ijpi(1−pi)\sum_{i\in I_j}p_i(1-p_i)∑i∈Ijpi(1−pi) 是逻辑目标的叶内曲率质量,并非严格意义上的“信息熵”或样本数。γ\gammaγ 判断一次合法切分的收益是否足以支付拓扑成本,而 min_child_weight 先判断子叶曲率质量是否达到准入下限。极端置信度下后者可能先阻断候选,此时调低 γ\gammaγ 也不会使该切分重新出现。
收缩步长与局部二次近似的有效范围
解析叶权 wj∗w_j^*wj∗ 是局部二次模型建议的完整位移,实际提升通常只走其中一部分:
Ft(x)=Ft−1(x)+ηft(x),0<η≤1.F_t(\boldsymbol{x})= F_{t-1}(\boldsymbol{x})+\eta f_t(\boldsymbol{x}), \qquad 0<\eta\leq 1. Ft(x)=Ft−1(x)+ηft(x),0<η≤1.
从离散动力系统看,η\etaη 是时间步长。较小的 η\etaη 降低二阶近似在远处失真的风险,也让后续树有机会修正当前树的结构偏差;代价是需要更多轮数。若把 η\etaη 调得极小却不增加树数,模型会欠拟合;若把 η\etaη 与树数同时开到极端,则只是让计算账单替代统计判断。
推导的适用边界
本章所有优雅公式都依赖局部二次近似与候选结构的贪心搜索。它们不能保证在全部树结构组成的离散空间中找到全局最优树,也不能让非凸、非二阶可微信号自动变得温顺。XGBoost 的“二阶”指每轮目标近似使用一阶梯度与对角二阶曲率,不等于对整座树结构空间做完整 Newton 优化。理解这条边界,能防止把一把精良扳手误认成宇宙定律。
参考文献
- Tianqi Chen, Carlos Guestrin. XGBoost: A Scalable Tree Boosting System. Proceedings of the 22nd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining,2016.
- XGBoost Developers. Categorical Data. https://xgboost.readthedocs.io/en/stable/tutorials/categorical.html
系列导航
- XGBoost 原理详解(一):模型定义、空间切分与二阶训练机制
- XGBoost 原理详解(二):目标函数、梯度、Hessian 与分裂增益推导(本文)
- XGBoost 工程实践(三):稀疏感知、生产 API、Optuna 调参与 NumPy 实现
- XGBoost 工程实践(四):压力测试、SHAP、因果边界与端到端案例
更多推荐


所有评论(0)