【HistGBM 系列②】梯度提升的数学框架与二阶优化
文章目录
- 【HistGBM 系列②】梯度提升的数学框架与二阶优化
-
- 前言
- 一、问题形式化
-
- 1.1 监督学习的函数估计视角
- 1.2 加性模型假设
- 二、Friedman 的梯度提升框架
-
- 2.1 核心困境
- 2.2 Friedman 的解法:函数空间的梯度下降
- 2.3 为什么这等价于梯度下降
- 2.4 以 MSE 为例验证
- 2.5 以 MAE 为例看框架的通用性
- 三、Friedman 通用算法
- 四、XGBoost 的二阶优化方法
-
- 4.1 为什么需要二阶信息
- 4.2 二阶泰勒展开
- 4.3 去掉常数项
- 4.4 按叶节点重组目标函数
- 4.5 最优叶权重:闭式解推导
- 4.6 分裂增益公式
- 五、常见损失函数的
(
g
i
,
h
i
)
(g_i, h_i)
(gi,hi) 计算 -
- 5.1 回归损失
- 5.2 二分类损失
- 5.3 Quantile Loss(分位数回归)
- 5.4 梯度计算的关键性质
- 六、
(
g
i
,
h
i
)
(g_i, h_i)
(gi,hi) 在 HistGBM 中的作用 -
- 6.1 直方图的存储内容
- 6.2 直方图相减的前提
- 6.3 一图总结
- 七、一阶 vs 二阶:一个直观的数值例子
- 八、小结
系列导航
- 【系列①】从决策树到梯度提升——GBDT 原理精讲
- 【系列②】梯度提升的数学框架与二阶优化(本篇)
- 【系列③】直方图加速——HistGBM 的核心创新
- 【系列④】HistGradientBoostingRegressor 深度解析
- 【系列⑤】调参实战与生产部署
前言
第一篇我们建立了从 CART 回归树到 GBDT 的完整认知,留下了一个悬念:对于 MSE 损失,伪残差恰好等于普通残差,那换了别的损失函数呢?
这正是 Friedman(2001)梯度提升框架的核心贡献:把 Boosting 的迭代过程统一为函数空间中的梯度下降。不管你用什么损失函数——MSE、MAE、Huber、Logistic Loss——算法结构完全不变,只需更换"梯度"的计算方式。
本篇将进一步引入 XGBoost(Chen & Guestrin, 2016)的二阶泰勒展开优化:不仅用一阶梯度告诉你"该往哪个方向走",还用二阶梯度(Hessian)告诉你"这一步迈多大最合适"。这两个统计量
(
g
i
,
h
i
)
(g_i, h_i)
(gi,hi) 正是 HistGBM 直方图的组成部分——理解它们对理解第三篇直方图加速至关重要。
本篇目标:
(
g
i
,
h
i
)
(g_i, h_i)
(gi,hi) 统计量的含义及其在 HistGBM 中的作用
一、问题形式化
1.1 监督学习的函数估计视角
给定训练数据
{
(
x
i
,
y
i
)
}
i
=
1
n
\\{(x_i, y_i)\\}_{i=1}^n
{(xi,yi)}i=1n,我们希望找到一个函数
F
(
x
)
F(x)
F(x) 来近似
y
y
y 与
x
x
x 之间的真实映射关系。
F
∗
=
arg
min
F
∑
i
=
1
n
L
(
y
i
,
F
(
x
i
)
)
F^* = \\arg\\min_F \\sum_{i=1}^n L(y_i, F(x_i))
F∗=argFmini=1∑nL(yi,F(xi))
其中
L
(
y
,
F
(
x
)
)
L(y, F(x))
L(y,F(x)) 是可微的损失函数,度量预测值
F
(
x
)
F(x)
F(x) 与真实值
y
y
y 之间的差异。
常见损失函数一览:
| Squared Error (MSE) |
1 2 ( y − F ) 2 \\frac{1}{2}(y-F)^2 21(y−F)2 |
对异常值敏感,梯度与残差成正比 | 普通回归(无异常值) |
| Absolute Error (MAE) | $ | y-F | $ |
| Huber Loss | $\\begin{cases} \\frac{1}{2}(y-F)^2 & | y-F | \\leq\\delta \\ \\delta |
| Logistic Loss |
log ( 1 + e − y ⋅ F ) \\log(1+e^{-y\\cdot F}) log(1+e−y⋅F) |
二分类标准损失 | 二分类 |
| Quantile Loss |
{ α ( y − F ) y > F ( 1 − α ) ( F − y ) y ≤ F \\begin{cases} \\alpha(y-F) & y>F \\\\ (1-\\alpha)(F-y) & y\\leq F \\end{cases} {α(y−F)(1−α)(F−y)y>Fy≤F |
可预测任意分位数 | 预测区间估计 |
1.2 加性模型假设
GBDT 假设模型
F
(
x
)
F(x)
F(x) 由 M 棵树的输出加性叠加而成:
F
M
(
x
)
=
∑
m
=
1
M
h
m
(
x
)
F_M(x) = \\sum_{m=1}^{M} h_m(x)
FM(x)=m=1∑Mhm(x)
其中每棵
h
m
(
x
)
h_m(x)
hm(x) 是一棵 CART 回归树,属于树函数空间
H
\\mathcal{H}
H。
这是一个"弱学习器的加权和"模型——单棵树能力有限(弱学习器),叠加起来就形成了强大的预测能力。
二、Friedman 的梯度提升框架
2.1 核心困境
如果我们想把
F
(
x
)
F(x)
F(x) 当作一个"参数"来优化,一个直接的思路是对
F
F
F 做梯度下降:
F
m
(
x
)
=
F
m
−
1
(
x
)
−
η
⋅
∂
∑
i
L
(
y
i
,
F
(
x
i
)
)
∂
F
F_m(x) = F_{m-1}(x) – \\eta \\cdot \\frac{\\partial \\sum_i L(y_i, F(x_i))}{\\partial F}
Fm(x)=Fm−1(x)−η⋅∂F∂∑iL(yi,F(xi))
但问题来了:
F
(
x
)
F(x)
F(x) 是一个函数,不是有限维参数向量。在全体训练样本上,
F
F
F 的"参数"是它在每个
x
i
x_i
xi 处的取值——共 n 个"参数"。而且,梯度只在训练点
(
x
i
,
y
i
)
(x_i, y_i)
(xi,yi) 处有定义——对于未见过的新
x
x
x,梯度没有意义。
2.2 Friedman 的解法:函数空间的梯度下降
第一步:在训练点上计算负梯度
第 m 轮迭代时,对每个训练样本计算损失函数对当前预测值的负梯度:
r
i
m
=
−
[
∂
L
(
y
i
,
F
(
x
i
)
)
∂
F
(
x
i
)
]
F
=
F
m
−
1
,
i
=
1
,
2
,
…
,
n
r_{im} = -\\left[\\frac{\\partial L(y_i, F(x_i))}{\\partial F(x_i)}\\right]_{F = F_{m-1}}, \\quad i = 1, 2, \\ldots, n
rim=−[∂F(xi)∂L(yi,F(xi))]F=Fm−1,i=1,2,…,n
这个
r
i
m
r_{im}
rim 被称为伪残差(pseudo-residual),它告诉你:为了让第 i 个样本的损失下降,
F
(
x
i
)
F(x_i)
F(xi) 应该往哪个方向调整。
第二步:用一棵树来"插值"梯度
负梯度只在 n 个训练点上定义了值,但我们需要的是能对任何新 x 做预测的函数。怎么办?
训练一棵回归树
h
m
(
x
)
h_m(x)
hm(x),用
{
(
x
i
,
r
i
m
)
}
i
=
1
n
\\{(x_i, r_{im})\\}_{i=1}^n
{(xi,rim)}i=1n 作为训练数据——让树去拟合这些负梯度值。直观理解:树"学会了"梯度在特征空间中的分布规律,可以对训练集之外的 x 也给出一个梯度方向的估计。
第三步:更新模型
F
m
(
x
)
=
F
m
−
1
(
x
)
+
η
⋅
h
m
(
x
)
F_m(x) = F_{m-1}(x) + \\eta \\cdot h_m(x)
Fm(x)=Fm−1(x)+η⋅hm(x)
η
\\eta
η 是学习率(shrinkage),控制每步的"步长"。
2.3 为什么这等价于梯度下降
考虑参数化模型的梯度下降更新:
θ
m
=
θ
m
−
1
−
η
⋅
∇
θ
L
(
θ
m
−
1
)
\\theta_m = \\theta_{m-1} – \\eta \\cdot \\nabla_\\theta L(\\theta_{m-1})
θm=θm−1−η⋅∇θL(θm−1)
对于 GBDT,"参数"是在每个训练点处的预测值
{
F
(
x
1
)
,
F
(
x
2
)
,
…
,
F
(
x
n
)
}
\\{F(x_1), F(x_2), \\ldots, F(x_n)\\}
{F(x1),F(x2),…,F(xn)}。在每个点上的梯度分量是
∂
L
∂
F
(
x
i
)
\\frac{\\partial L}{\\partial F(x_i)}
∂F(xi)∂L,所以:
(
F
m
(
x
1
)
F
m
(
x
2
)
⋮
F
m
(
x
n
)
)
=
(
F
m
−
1
(
x
1
)
F
m
−
1
(
x
2
)
⋮
F
m
−
1
(
x
n
)
)
+
η
⋅
(
−
r
1
m
−
r
2
m
⋮
−
r
n
m
)
\\begin{pmatrix} F_m(x_1) \\\\ F_m(x_2) \\\\ \\vdots \\\\ F_m(x_n) \\end{pmatrix} = \\begin{pmatrix} F_{m-1}(x_1) \\\\ F_{m-1}(x_2) \\\\ \\vdots \\\\ F_{m-1}(x_n) \\end{pmatrix} + \\eta \\cdot \\begin{pmatrix} -r_{1m} \\\\ -r_{2m} \\\\ \\vdots \\\\ -r_{nm} \\end{pmatrix}
Fm(x1)Fm(x2)⋮Fm(xn)
=
Fm−1(x1)Fm−1(x2)⋮Fm−1(xn)
+η⋅
−r1m−r2m⋮−rnm
但
h
m
(
x
)
h_m(x)
hm(x) 并非完美拟合这些
r
i
m
r_{im}
rim——树是有限深度的,只能近似。树将负梯度"约束"为一个结构化的函数(分段常数),这赋予了两个好处:
2.4 以 MSE 为例验证
对于 MSE 损失
L
(
y
,
F
)
=
1
2
(
y
−
F
)
2
L(y, F) = \\frac{1}{2}(y – F)^2
L(y,F)=21(y−F)2:
r
i
m
=
−
[
∂
1
2
(
y
i
−
F
)
2
∂
F
]
F
=
F
m
−
1
=
−
[
−
(
y
i
−
F
m
−
1
(
x
i
)
)
]
=
y
i
−
F
m
−
1
(
x
i
)
r_{im} = -\\left[\\frac{\\partial \\frac{1}{2}(y_i – F)^2}{\\partial F}\\right]_{F=F_{m-1}} = -[-(y_i – F_{m-1}(x_i))] = y_i – F_{m-1}(x_i)
rim=−[∂F∂21(yi−F)2]F=Fm−1=−[−(yi−Fm−1(xi))]=yi−Fm−1(xi)
伪残差 = 普通残差。这就是为什么 GBDT 有时被通俗地称为"拟合残差的树模型"——对 MSE 而言确实如此。
2.5 以 MAE 为例看框架的通用性
对于 MAE 损失
L
(
y
,
F
)
=
∣
y
−
F
∣
L(y, F) = |y – F|
L(y,F)=∣y−F∣:
r
i
m
=
−
[
∂
∣
y
i
−
F
∣
∂
F
]
F
=
F
m
−
1
=
sign
(
y
i
−
F
m
−
1
(
x
i
)
)
r_{im} = -\\left[\\frac{\\partial |y_i – F|}{\\partial F}\\right]_{F=F_{m-1}} = \\text{sign}(y_i – F_{m-1}(x_i))
rim=−[∂F∂∣yi−F∣]F=Fm−1=sign(yi−Fm−1(xi))
伪残差变为 +1 或 -1(取决于预测是高是低),不再是残差值本身。但算法结构完全不变——这正是梯度提升"框架"的威力。
三、Friedman 通用算法
基于以上推导,Friedman 的通用梯度提升算法如下:
算法:Generic Gradient Boosting Machine(Friedman 2001)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
输入:训练集 {(x_i, y_i)}_{i=1}^n
可微损失函数 L(y, F)
迭代次数 M
学习率 η
1. 初始化常数值预测:
F_0(x) = argmin_γ Σ_{i=1}^n L(y_i, γ)
(常见:MSE 时取均值,MAE 时取中位数)
2. For m = 1 to M:
a. 计算伪残差(负梯度):
r_{im} = -[∂L(y_i, F(x_i)) / ∂F(x_i)]_{F=F_{m-1}}, i=1,…,n
b. 用回归树拟合 {(x_i, r_{im})}:
{R_{jm}}_{j=1}^{J_m} = J_m 个叶节点区域
c. 对每个叶节点 j,计算最优预测值(一维线搜索):
γ_{jm} = argmin_γ Σ_{x_i∈R_{jm}} L(y_i, F_{m-1}(x_i) + γ)
d. 更新模型:
F_m(x) = F_{m-1}(x) + η · Σ_{j=1}^{J_m} γ_{jm} · 1[x∈R_{jm}]
3. 输出:F_M(x)
📌 注意步骤 2c:Friedman 原始方案在每个叶节点上做一个一维线搜索来找最优 γ。这理论上更精确,但计算量大。XGBoost 和 HistGBM 用一个更聪明的方法——二阶泰勒展开——直接用闭式解替代线搜索。这就引出了下一节的核心内容。
四、XGBoost 的二阶优化方法
4.1 为什么需要二阶信息
Friedman 的一阶框架有一个不够优雅的地方:步骤 2c 的线搜索需要在每个叶节点上求一个最优化子问题。
能不能直接算出最优叶权重,省去线搜索?
这就需要用二阶泰勒展开来近似损失函数——不仅知道梯度的方向(一阶),还知道曲率(二阶),从而直接算出最优步长。
4.2 二阶泰勒展开
在第 t 轮迭代,当前模型为
y
^
i
(
t
−
1
)
=
F
t
−
1
(
x
i
)
\\hat{y}_i^{(t-1)} = F_{t-1}(x_i)
y^i(t−1)=Ft−1(xi),我们要找一个新树
f
t
f_t
ft 使得:
L
(
t
)
=
∑
i
=
1
n
L
(
y
i
,
y
^
i
(
t
−
1
)
+
f
t
(
x
i
)
)
+
Ω
(
f
t
)
\\mathcal{L}^{(t)} = \\sum_{i=1}^n L(y_i, \\hat{y}_i^{(t-1)} + f_t(x_i)) + \\Omega(f_t)
L(t)=i=1∑nL(yi,y^i(t−1)+ft(xi))+Ω(ft)
在
y
^
i
(
t
−
1
)
\\hat{y}_i^{(t-1)}
y^i(t−1) 处对损失函数做二阶泰勒展开:
L
(
y
i
,
y
^
(
t
−
1
)
+
f
t
)
≈
L
(
y
i
,
y
^
(
t
−
1
)
)
+
g
i
⋅
f
t
(
x
i
)
+
1
2
h
i
⋅
f
t
2
(
x
i
)
L(y_i, \\hat{y}^{(t-1)} + f_t) \\approx L(y_i, \\hat{y}^{(t-1)}) + g_i \\cdot f_t(x_i) + \\frac{1}{2} h_i \\cdot f_t^2(x_i)
L(yi,y^(t−1)+ft)≈L(yi,y^(t−1))+gi⋅ft(xi)+21hi⋅ft2(xi)
其中:
g
i
=
∂
L
(
y
i
,
y
^
)
∂
y
^
∣
y
^
=
y
^
i
(
t
−
1
)
— 一阶梯度(等同于 Friedman 的负伪残差,取负号)
g_i = \\frac{\\partial L(y_i, \\hat{y})}{\\partial \\hat{y}} \\Big|_{\\hat{y}=\\hat{y}_i^{(t-1)}} \\quad \\text{— 一阶梯度(等同于 Friedman 的负伪残差,取负号)}
gi=∂y^∂L(yi,y^)
y^=y^i(t−1)— 一阶梯度(等同于 Friedman 的负伪残差,取负号)
h
i
=
∂
2
L
(
y
i
,
y
^
)
∂
y
^
2
∣
y
^
=
y
^
i
(
t
−
1
)
— 二阶梯度(Hessian,度量损失函数的曲率)
h_i = \\frac{\\partial^2 L(y_i, \\hat{y})}{\\partial \\hat{y}^2} \\Big|_{\\hat{y}=\\hat{y}_i^{(t-1)}} \\quad \\text{— 二阶梯度(Hessian,度量损失函数的曲率)}
hi=∂y^2∂2L(yi,y^)
y^=y^i(t−1)— 二阶梯度(Hessian,度量损失函数的曲率)
💡 为什么二阶更好? 一阶只告诉你"该往哪个方向走",二阶告诉你"曲率有多陡"——如果
h
i
h_i
hi 很大(损失函数曲率大),意味着该点附近的梯度变化剧烈,应该走小步;如果
h
i
h_i
hi 很小(损失函数平坦),可以走大步。
4.3 去掉常数项
常数项
L
(
y
i
,
y
^
(
t
−
1
)
)
L(y_i, \\hat{y}^{(t-1)})
L(yi,y^(t−1)) 不依赖
f
t
f_t
ft,可以去掉。加上正则项后,近似目标函数为:
L
~
(
t
)
=
∑
i
=
1
n
[
g
i
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
]
+
Ω
(
f
t
)
\\tilde{\\mathcal{L}}^{(t)} = \\sum_{i=1}^n \\left[g_i f_t(x_i) + \\frac{1}{2} h_i f_t^2(x_i)\\right] + \\Omega(f_t)
L~(t)=i=1∑n[gift(xi)+21hift2(xi)]+Ω(ft)
正则项:
Ω
(
f
t
)
=
γ
T
+
1
2
λ
∑
j
=
1
T
w
j
2
\\Omega(f_t) = \\gamma T + \\frac{1}{2}\\lambda \\sum_{j=1}^T w_j^2
Ω(ft)=γT+21λj=1∑Twj2
其中:
-
T
T
T:树的叶节点数量 -
w
j
w_j
wj:第j
j
j 个叶节点的权重(输出值) -
γ
\\gamma
γ:新增一个叶节点的复杂度代价(类似剪枝强度) -
λ
\\lambda
λ:叶节点权重的 L2 正则化系数
🎯 两个正则化参数的区别:
γ
\\gamma
γ 控制"树可以长多大"(结构复杂度),
λ
\\lambda
λ 控制"每个预测值可以多大"(权重约束)。HistGBM 和 sklearn 的 l2_regularization 对应
λ
\\lambda
λ。
4.4 按叶节点重组目标函数
一棵树将样本分配到了
T
T
T 个叶节点。定义
I
j
=
{
i
∣
x
i
∈
叶节点
j
}
I_j = \\{i \\mid x_i \\in \\text{叶节点} j\\}
Ij={i∣xi∈叶节点j} 为被分配到第
j
j
j 个叶节点的样本索引集合。
由于
f
t
(
x
i
)
=
w
q
(
x
i
)
f_t(x_i) = w_{q(x_i)}
ft(xi)=wq(xi)(即样本
x
i
x_i
xi 的输出值等于其所在叶节点的权重),目标函数改写为:
L
~
(
t
)
=
∑
j
=
1
T
[
(
∑
i
∈
I
j
g
i
)
⏟
G
j
w
j
+
1
2
(
∑
i
∈
I
j
h
i
+
λ
)
⏟
H
j
+
λ
w
j
2
]
+
γ
T
\\tilde{\\mathcal{L}}^{(t)} = \\sum_{j=1}^T \\left[ \\underbrace{\\left(\\sum_{i \\in I_j} g_i\\right)}_{G_j} w_j + \\frac{1}{2} \\underbrace{\\left(\\sum_{i \\in I_j} h_i + \\lambda\\right)}_{H_j + \\lambda} w_j^2 \\right] + \\gamma T
L~(t)=j=1∑T
Gj
i∈Ij∑gi
wj+21Hj+λ
i∈Ij∑hi+λ
wj2
+γT
定义两个关键的聚合统计量:
G
j
=
∑
i
∈
I
j
g
i
— 叶节点 j 的一阶梯度和
G_j = \\sum_{i \\in I_j} g_i \\quad \\text{— 叶节点 j 的一阶梯度和}
Gj=i∈Ij∑gi— 叶节点 j 的一阶梯度和
H
j
=
∑
i
∈
I
j
h
i
— 叶节点 j 的二阶梯度和
H_j = \\sum_{i \\in I_j} h_i \\quad \\text{— 叶节点 j 的二阶梯度和}
Hj=i∈Ij∑hi— 叶节点 j 的二阶梯度和
4.5 最优叶权重:闭式解推导
对每个叶节点
j
j
j,它的子目标函数(只含
w
j
w_j
wj 的部分)是:
L
j
(
w
j
)
=
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
\\mathcal{L}_j(w_j) = G_j w_j + \\frac{1}{2}(H_j + \\lambda) w_j^2
Lj(wj)=Gjwj+21(Hj+λ)wj2
这是一个关于
w
j
w_j
wj 的二次函数!对
w
j
w_j
wj 求导并令其为零:
∂
L
j
∂
w
j
=
G
j
+
(
H
j
+
λ
)
w
j
=
0
\\frac{\\partial \\mathcal{L}_j}{\\partial w_j} = G_j + (H_j + \\lambda) w_j = 0
∂wj∂Lj=Gj+(Hj+λ)wj=0
最优叶权重(闭式解):
w
j
∗
=
−
G
j
H
j
+
λ
\\boxed{w_j^* = -\\frac{G_j}{H_j + \\lambda}}
wj∗=−Hj+λGj
这个公式值得多看几眼:
- 分子
G
j
G_j
Gj:该叶节点所有样本的一阶梯度之和。如果样本的预测偏低(g
i
>
0
g_i > 0
gi>0,即y
^
<
y
\\hat{y} < y
y^<y),G
j
G_j
Gj 为正,则w
j
∗
w_j^*
wj∗ 为负——权重向下拉,提高预测值。 - 分母
H
j
+
λ
H_j + \\lambda
Hj+λ:二阶梯度之和 + 正则化。H
j
H_j
Hj 越大(曲率越大),步长越小(更谨慎);λ
\\lambda
λ 越大,步长也越小(更强的正则化收缩)。
代入目标函数,得到该树结构下的最优目标值(用于衡量树结构有多好):
L
~
(
t
)
(
q
)
=
−
1
2
∑
j
=
1
T
G
j
2
H
j
+
λ
+
γ
T
\\boxed{\\tilde{\\mathcal{L}}^{(t)}(q) = -\\frac{1}{2} \\sum_{j=1}^T \\frac{G_j^2}{H_j + \\lambda} + \\gamma T}
L~(t)(q)=−21j=1∑THj+λGj2+γT
4.6 分裂增益公式
有了结构评分函数,我们就可以精确地评估一个分裂有多好。
分裂前,父节点的"分数"是:
Score
parent
=
−
1
2
(
G
L
+
G
R
)
2
H
L
+
H
R
+
λ
+
γ
×
1
\\text{Score}_{\\text{parent}} = -\\frac{1}{2} \\frac{(G_L + G_R)^2}{H_L + H_R + \\lambda} + \\gamma \\times 1
Scoreparent=−21HL+HR+λ(GL+GR)2+γ×1
分裂后,左右子节点的"分数"之和是:
Score
children
=
−
1
2
[
G
L
2
H
L
+
λ
+
G
R
2
H
R
+
λ
]
+
γ
×
2
\\text{Score}_{\\text{children}} = -\\frac{1}{2} \\left[ \\frac{G_L^2}{H_L + \\lambda} + \\frac{G_R^2}{H_R + \\lambda} \\right] + \\gamma \\times 2
Scorechildren=−21[HL+λGL2+HR+λGR2]+γ×2
分裂增益 = Score(分裂后) − Score(分裂前):
Gain
=
1
2
[
G
L
2
H
L
+
λ
+
G
R
2
H
R
+
λ
−
(
G
L
+
G
R
)
2
H
L
+
H
R
+
λ
]
−
γ
\\boxed{\\text{Gain} = \\frac{1}{2} \\left[ \\frac{G_L^2}{H_L + \\lambda} + \\frac{G_R^2}{H_R + \\lambda} – \\frac{(G_L + G_R)^2}{H_L + H_R + \\lambda} \\right] – \\gamma}
Gain=21[HL+λGL2+HR+λGR2−HL+HR+λ(GL+GR)2]−γ
🎯 这就是 HistGBM 直方图要计算的公式:给定左右子节点的
(
G
L
,
H
L
)
(G_L, H_L)
(GL,HL) 和
(
G
R
,
H
R
)
(G_R, H_R)
(GR,HR),就能算出分裂增益。而直方图中每个 bin 恰好存储的就是
(
G
b
,
H
b
)
(G_b, H_b)
(Gb,Hb) 的累加值。
五、常见损失函数的
(
g
i
,
h
i
)
(g_i, h_i)
(gi,hi) 计算
不同损失函数的
(
g
i
,
h
i
)
(g_i, h_i)
(gi,hi) 不同。下表列出了几种常见损失函数的具体形式:
5.1 回归损失
Squared Error(MSE):
L
(
y
,
y
^
)
=
1
2
(
y
−
y
^
)
2
L(y, \\hat{y}) = \\frac{1}{2}(y – \\hat{y})^2
L(y,y^)=21(y−y^)2
g
i
=
y
^
i
−
y
i
h
i
=
1
g_i = \\hat{y}_i – y_i \\qquad h_i = 1
gi=y^i−yihi=1
💡 注意
h
i
=
1
h_i = 1
hi=1 恒为常数——MSE 是二次函数,曲率处处相同。这也是为什么传统的残差拟合就能做得很好:二阶信息没有提供额外的"曲率差异"。
Absolute Error(MAE):
L
(
y
,
y
^
)
=
∣
y
−
y
^
∣
L(y, \\hat{y}) = |y – \\hat{y}|
L(y,y^)=∣y−y^∣
g
i
=
sign
(
y
^
i
−
y
i
)
h
i
=
0
g_i = \\text{sign}(\\hat{y}_i – y_i) \\qquad h_i = 0
gi=sign(y^i−yi)hi=0
⚠️
h
i
=
0
h_i = 0
hi=0 是问题所在——
H
j
H_j
Hj 可能为 0,导致
w
j
∗
=
−
G
j
/
λ
w_j^* = -G_j / \\lambda
wj∗=−Gj/λ,完全依赖
λ
\\lambda
λ 来防止除零。
Huber Loss:在
δ
\\delta
δ 以内用 MSE,以外用 MAE
g
i
=
{
y
^
i
−
y
i
∣
y
^
i
−
y
i
∣
≤
δ
δ
⋅
sign
(
y
^
i
−
y
i
)
∣
y
^
i
−
y
i
∣
>
δ
g_i = \\begin{cases} \\hat{y}_i – y_i & |\\hat{y}_i – y_i| \\leq \\delta \\\\ \\delta \\cdot \\text{sign}(\\hat{y}_i – y_i) & |\\hat{y}_i – y_i| > \\delta \\end{cases}
gi={y^i−yiδ⋅sign(y^i−yi)∣y^i−yi∣≤δ∣y^i−yi∣>δ
h
i
=
{
1
∣
y
^
i
−
y
i
∣
≤
δ
0
∣
y
^
i
−
y
i
∣
>
δ
h_i = \\begin{cases} 1 & |\\hat{y}_i – y_i| \\leq \\delta \\\\ 0 & |\\hat{y}_i – y_i| > \\delta \\end{cases}
hi={10∣y^i−yi∣≤δ∣y^i−yi∣>δ
5.2 二分类损失
Binary Log Loss:
L
(
y
,
y
^
)
=
−
y
log
(
σ
(
y
^
)
)
−
(
1
−
y
)
log
(
1
−
σ
(
y
^
)
)
L(y, \\hat{y}) = -y\\log(\\sigma(\\hat{y})) – (1-y)\\log(1-\\sigma(\\hat{y}))
L(y,y^)=−ylog(σ(y^))−(1−y)log(1−σ(y^)),其中
σ
\\sigma
σ 为 sigmoid 函数
g
i
=
σ
(
y
^
i
)
−
y
i
h
i
=
σ
(
y
^
i
)
⋅
(
1
−
σ
(
y
^
i
)
)
g_i = \\sigma(\\hat{y}_i) – y_i \\qquad h_i = \\sigma(\\hat{y}_i) \\cdot (1 – \\sigma(\\hat{y}_i))
gi=σ(y^i)−yihi=σ(y^i)⋅(1−σ(y^i))
💡 分类任务中
h
i
≠
1
h_i \\neq 1
hi=1,二阶信息包含了概率预测的不确定性。当
σ
(
y
^
i
)
≈
0.5
\\sigma(\\hat{y}_i) \\approx 0.5
σ(y^i)≈0.5(不确定),
h
i
≈
0.25
h_i \\approx 0.25
hi≈0.25 最大;当
σ
(
y
^
i
)
≈
0
\\sigma(\\hat{y}_i) \\approx 0
σ(y^i)≈0 或
1
1
1(确定),
h
i
≈
0
h_i \\approx 0
hi≈0。
5.3 Quantile Loss(分位数回归)
g
i
=
{
α
if
y
i
>
y
^
i
α
−
1
if
y
i
≤
y
^
i
g_i = \\begin{cases} \\alpha & \\text{if } y_i > \\hat{y}_i \\\\ \\alpha – 1 & \\text{if } y_i \\leq \\hat{y}_i \\end{cases}
gi={αα−1if yi>y^iif yi≤y^i
h
i
=
0
h_i = 0
hi=0
训练多个分位数的模型(如 α=0.1, 0.5, 0.9),可以得到预测区间,量化预测的不确定性。scikit-learn 的 HistGradientBoostingRegressor(loss='quantile', quantile=0.9) 正是基于此。
5.4 梯度计算的关键性质
|
( g i , h i ) (g_i, h_i) (gi,hi) 只依赖当前预测值和真实标签 |
每轮迭代开始时即可计算,完全独立于树的构建过程 |
|
h i ≥ 0 h_i \\geq 0 hi≥0(对大多数凸损失函数) |
二阶导非负,
H j + λ > 0 H_j + \\lambda > 0 Hj+λ>0 保证分母不为零 |
| MSE 下
h i = 1 h_i = 1 hi=1 |
退化为一阶方法,验证框架的一致性 |
六、
(
g
i
,
h
i
)
(g_i, h_i)
(gi,hi) 在 HistGBM 中的作用
6.1 直方图的存储内容
HistGBM 的直方图中,每个 bin 存储的不是原始特征值的计数,而是该 bin 内所有样本的梯度统计量:
Hist
(
k
,
b
)
=
(
∑
i
:
x
i
k
∈
bin
b
g
i
,
∑
i
:
x
i
k
∈
bin
b
h
i
,
∣
{
i
:
x
i
k
∈
bin
b
}
∣
)
\\text{Hist}(k, b) = \\left( \\sum_{i: x_{ik} \\in \\text{bin}_b} g_i,\\quad \\sum_{i: x_{ik} \\in \\text{bin}_b} h_i,\\quad |\\{i: x_{ik} \\in \\text{bin}_b\\}| \\right)
Hist(k,b)=(i:xik∈binb∑gi,i:xik∈binb∑hi,∣{i:xik∈binb}∣)
有了
(
G
,
H
)
(G, H)
(G,H),就可以用分裂增益公式直接评估任何分裂点的效果——这正是第三篇要详细展开的核心。
6.2 直方图相减的前提
父节点直方图 = 左子节点直方图 + 右子节点直方图——这个"线性可加性"是因为
(
g
i
,
h
i
)
(g_i, h_i)
(gi,hi) 在分裂前已经算好,它们对当前迭代是固定的常数。所以:
G
right
=
G
parent
−
G
left
,
H
right
=
H
parent
−
H
left
G_{\\text{right}} = G_{\\text{parent}} – G_{\\text{left}}, \\quad H_{\\text{right}} = H_{\\text{parent}} – H_{\\text{left}}
Gright=Gparent−Gleft,Hright=Hparent−Hleft
6.3 一图总结
梯度计算(每轮迭代开始时)
╔══════════════════════════════════════╗
║ 当前预测 F_{m-1}(x_i) ║
║ ↓ ║
║ 计算 g_i = ∂L/∂F, h_i = ∂²L/∂F² ║
║ ↓ ║
║ (g_i, h_i) 作为固定统计量 ║
║ 输送给直方图构建 ║
╚══════════════════════════════════════╝
↓
直方图构建(第三篇详述)
╔══════════════════════════════════════╗
║ 对每个 bin b: ║
║ G_b = Σ_{i∈bin_b} g_i ║
║ H_b = Σ_{i∈bin_b} h_i ║
║ ↓ ║
║ 分裂增益 = f(G_L, H_L, G_R, H_R) ║
╚══════════════════════════════════════╝
↓
最优叶权重(本篇公式)
╔══════════════════════════════════════╗
║ w_j* = -G_j / (H_j + λ) ║
║ 叶节点输出 = η · w_j* ║
╚══════════════════════════════════════╝
七、一阶 vs 二阶:一个直观的数值例子
假设一个叶节点中有三个样本,当前预测值都是
y
^
=
2.0
\\hat{y} = 2.0
y^=2.0:
| A | 5.0 | MSE | 2.0 – 5.0 = -3.0 | 1 |
| B | 3.0 | MSE | 2.0 – 3.0 = -1.0 | 1 |
| C | 1.0 | MSE | 2.0 – 1.0 = 1.0 | 1 |
一阶方法(传统 GBDT):叶节点输出 = 三个残差的均值 =
(
−
3.0
−
1.0
+
1.0
)
/
3
=
−
1.0
(-3.0 – 1.0 + 1.0) / 3 = -1.0
(−3.0−1.0+1.0)/3=−1.0
二阶方法(XGBoost/HistGBM):
G
j
=
−
3.0
−
1.0
+
1.0
=
−
3.0
G_j = -3.0 – 1.0 + 1.0 = -3.0
Gj=−3.0−1.0+1.0=−3.0
H
j
=
1
+
1
+
1
=
3
H_j = 1 + 1 + 1 = 3
Hj=1+1+1=3
w
j
∗
=
−
−
3.0
3
+
0
=
1.0
(与一阶一致,因为 MSE 下
h
i
=
1
)
w_j^* = -\\frac{-3.0}{3 + 0} = 1.0 \\quad \\text{(与一阶一致,因为 MSE 下 } h_i=1 \\text{)}
wj∗=−3+0−3.0=1.0(与一阶一致,因为 MSE 下 hi=1)
引入 L2 正则化(
λ
=
1.0
\\lambda = 1.0
λ=1.0):
w
j
∗
=
−
−
3.0
3
+
1
=
0.75
w_j^* = -\\frac{-3.0}{3 + 1} = 0.75
wj∗=−3+1−3.0=0.75
正则化将权重从 1.0 收缩到 0.75——防止模型对某几个样本"过度反应"。
现在换成二分类任务(LogLoss):
| D | 0.9 (很确定是正类) | 1 | 0.9 – 1 = -0.1 | 0.9×0.1 = 0.09 |
| E | 0.5 (不确定) | 0 | 0.5 – 0 = 0.5 | 0.5×0.5 = 0.25 |
注意
h
D
=
0.09
h_D = 0.09
hD=0.09(几乎确定,曲率小),
h
E
=
0.25
h_E = 0.25
hE=0.25(最不确定,曲率大)。二阶信息自然地给不确定样本更大的影响权重——没有一阶方法可以做这种区分。
八、小结
本篇完成了梯度提升理论的完整数学搭建:
| Friedman 框架 | Boosting = 函数空间的梯度下降 |
r i m = − ∂ L / ∂ F r_{im} = -\\partial L / \\partial F rim=−∂L/∂F |
| 伪残差 | 负梯度方向,替代普通残差(MSE 时两者等价) |
r i m r_{im} rim 随损失函数而变 |
| 二阶泰勒展开 | 用 Hessian 捕捉曲率信息 |
L ≈ g i f t + 1 2 h i f t 2 \\mathcal{L} \\approx g_i f_t + \\frac{1}{2} h_i f_t^2 L≈gift+21hift2 |
| 最优叶权重 | 二次函数的闭式解 |
w j ∗ = − G j / ( H j + λ ) w_j^* = -G_j / (H_j + \\lambda) wj∗=−Gj/(Hj+λ) |
| 分裂增益 | 量化分裂好坏的标准 |
Gain = 1 2 [ G L 2 / ( H L + λ ) + … ] − γ \\text{Gain} = \\frac{1}{2}[G_L^2/(H_L+\\lambda) + \\dots] – \\gamma Gain=21[GL2/(HL+λ)+…]−γ |
| 直方图统计量 | 直方图 bin 中存储的内容 |
( G b , H b ) = ( ∑ g i , ∑ h i ) (G_b, H_b) = (\\sum g_i, \\sum h_i) (Gb,Hb)=(∑gi,∑hi) |
关键洞察:
-
(
g
i
,
h
i
)
(g_i, h_i)
(gi,hi) 是贯通整个 HistGBM 系统的"血液"——每轮迭代开始时计算一次,然后被直方图聚合、被增益公式使用、被叶权重公式使用 - 二阶信息的价值在 MSE 场景下不显著(
h
i
=
1
h_i=1
hi=1 为常数),但在分类、分位数回归等任务中提供了额外的曲率信息 - 理解
(
g
i
,
h
i
)
(g_i, h_i)
(gi,hi) 是理解下一篇直方图加速的必要前提
下一篇将把这些数学公式与工程实现对接——直方图分箱如何将 n 个样本压缩为 B 个 bin,如何构建梯度直方图,以及直方图相减技巧如何将分裂速度提升数千倍。
参考资料



