XGBoost公式推导
假如目标函数
O
b
j
t
(
f
t
(
x
i
)
)
=
∑
i
=
1
N
L
(
y
i
,
y
i
t
−
1
+
f
m
(
x
i
)
)
+
Ω
(
f
t
)
+
C
Obj^{t}(f_t(x_i))=\sum_{i=1}^NL(y_i,y_i^{t-1}+f_m(x_i))+\Omega(f_t)+C
Objt(ft(xi))=∑i=1NL(yi,yit−1+fm(xi))+Ω(ft)+C。我们知道对于一个
n
n
n阶可导的函数
f
(
x
)
f(x)
f(x)我们可以通过泰勒展开式将其展开:
f
(
x
+
Δ
x
)
=
f
(
Δ
x
)
+
f
′
(
x
)
Δ
x
+
f
′
′
(
x
)
Δ
2
2
!
+
…
+
f
n
(
x
0
)
(
Δ
)
n
n
!
f(x+\Delta x) = f(\Delta x)+f'(x)\Delta x+f''(x)\frac{\Delta^2}{2!}+\ldots+f^{n}(x_0)\frac{(\Delta)^n}{n!}
f(x+Δx)=f(Δx)+f′(x)Δx+f′′(x)2!Δ2+…+fn(x0)n!(Δ)n
因此我们可以对泰勒公式做简单的近似:
f
(
x
+
Δ
x
)
≈
f
(
Δ
x
)
+
f
′
(
x
)
Δ
x
+
f
′
′
(
x
)
Δ
2
2
!
f(x+\Delta x) \approx f(\Delta x)+f'(x)\Delta x+f''(x)\frac{\Delta^2}{2!}
f(x+Δx)≈f(Δx)+f′(x)Δx+f′′(x)2!Δ2
O
b
j
t
(
f
t
)
=
∑
i
=
1
N
L
(
y
i
,
y
i
t
−
1
+
f
t
(
x
i
)
)
+
Ω
(
f
t
(
x
i
)
)
+
C
=
∑
i
=
1
N
[
L
(
y
i
,
y
i
t
−
1
)
+
∂
L
(
y
i
,
y
i
t
−
1
)
∂
y
i
t
−
1
f
t
(
x
i
)
+
1
2
∂
2
L
(
y
i
,
y
i
t
−
1
)
∂
2
y
i
t
−
1
f
t
(
x
i
)
2
]
+
Ω
(
f
t
(
x
i
)
)
+
C
Obj^{t}(f_t)=\sum_{i=1}^NL(y_i,y_i^{t-1}+f_t(x_i))+\Omega(f_t(x_i))+C\\ =\sum_{i=1}^N\left[L(y_i,y_i^{t-1})+\frac{\partial L(y_i,y_i^{t-1})}{\partial y_i^{t-1}}f_t(x_i)+\frac{1}{2}\frac{\partial^2L(y_i,y_i^{t-1})}{\partial^2y_i^{t-1}}f_t(x_i)^2\right]+\Omega(f_t(x_i))+C
Objt(ft)=i=1∑NL(yi,yit−1+ft(xi))+Ω(ft(xi))+C=i=1∑N[L(yi,yit−1)+∂yit−1∂L(yi,yit−1)ft(xi)+21∂2yit−1∂2L(yi,yit−1)ft(xi)2]+Ω(ft(xi))+C
y
i
t
−
1
y_i^{t-1}
yit−1表示前
t
−
1
t-1
t−1棵数得到的模型,
f
t
(
x
i
)
f_t(x_i)
ft(xi)表示加入第
t
t
t棵树。集成算法的目的是通过加入一颗新的数让损失变得更小。
i
i
i为样本序号,
Ω
\Omega
Ω为第t棵数的正则化后的表达式,正如上面讲的,可表示如下:
Ω
(
f
t
)
=
γ
T
+
λ
1
2
∑
j
=
1
T
w
j
2
\Omega(f_t)=\gamma T+\lambda\frac{1}{2}\sum_{j=1}^Tw_j^2
Ω(ft)=γT+λ21j=1∑Twj2
其中
T
T
T表示树的节点个数、
γ
\gamma
γ是惩罚因子(树的节点越多越容易过拟合)。然后对于决策树而言,最重要的就是一共有多少个节点以及每个节点的权值,所以决策树可以表示为:
f
m
(
x
)
=
∑
j
=
1
J
w
j
I
j
(
x
∈
R
j
)
f_m(x)=\sum_{j=1}^Jw_jI_j(x\in R_j)
fm(x)=j=1∑JwjIj(x∈Rj)
其中:
I
i
(
x
∈
R
j
)
I_i(x\in R_j)
Ii(x∈Rj)表示第
j
j
j个叶子节点的所有样本
x
i
x_i
xi属于此节点,对于式\ref{eq:obj_simple}做下面的简化:
g
i
=
∂
L
(
y
i
,
y
i
t
−
1
)
∂
y
i
t
−
1
h
i
=
∂
2
L
(
y
i
,
y
i
t
−
1
)
∂
2
y
i
t
−
1
g_i=\frac{\partial L(y_i,y_i^{t-1})}{\partial y_i^{t-1}}\\ h_i=\frac{\partial^2L(y_i,y_i^{t-1})}{\partial^2y_i^{t-1}}
gi=∂yit−1∂L(yi,yit−1)hi=∂2yit−1∂2L(yi,yit−1)
这样就有了下一步的推导,
O
b
j
t
(
f
i
)
≈
∑
i
=
1
n
[
L
(
y
i
,
y
^
i
(
t
−
1
)
)
+
g
i
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
]
+
Ω
(
f
t
)
+
C
=
∑
i
=
1
n
[
g
i
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
]
+
Ω
(
f
t
)
+
C
=
∑
i
=
1
n
[
g
i
w
q
(
x
i
)
+
1
2
h
i
w
q
(
x
i
)
2
]
+
γ
⋅
T
+
λ
⋅
1
2
∑
j
=
1
T
w
j
2
+
C
=
∑
j
=
1
T
[
(
∑
i
∈
I
j
g
i
)
w
j
+
1
2
(
∑
i
∈
I
j
h
i
)
w
j
2
]
+
γ
⋅
T
+
λ
⋅
1
2
∑
j
=
1
T
w
j
2
+
C
=
∑
j
=
1
T
[
(
∑
i
∈
I
j
g
i
)
w
j
+
1
2
(
∑
i
∈
I
j
h
i
+
λ
)
w
j
2
]
+
γ
⋅
T
+
C
Obj^{t}(f_i)\approx \sum_{i=1}^n\left[L(y_i,\hat{y}_i^{(t-1)})+g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)\right]+\Omega(f_t)+C\\ =\sum_{i=1}^n\left[g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)\right]+\Omega(f_t)+C\\ =\sum_{i=1}^n\left[g_iw_{q(x_i)}+\frac{1}{2}h_iw^2_{q(x_i)}\right]+\gamma\cdot T+\lambda\cdot \frac{1}{2}\sum_{j=1}^Tw_j^2+C\\ =\sum_{j=1}^T\left[\left(\sum_{i\in I_j}g_i\right)w_j+\frac{1}{2}\left(\sum_{i\in I_j}h_i\right)w_j^2\right]+\gamma\cdot T+\lambda\cdot \frac{1}{2}\sum_{j=1}^Tw_j^2+C\\ =\sum_{j=1}^T\left[\left(\sum_{i\in I_j} g_i\right)w_j+\frac{1}{2}\left(\sum_{i\in I_j}h_i+\lambda\right)w_j^2\right]+\gamma\cdot T+C
Objt(fi)≈i=1∑n[L(yi,y^i(t−1))+gift(xi)+21hift2(xi)]+Ω(ft)+C=i=1∑n[gift(xi)+21hift2(xi)]+Ω(ft)+C=i=1∑n[giwq(xi)+21hiwq(xi)2]+γ⋅T+λ⋅21j=1∑Twj2+C=j=1∑T⎣⎡⎝⎛i∈Ij∑gi⎠⎞wj+21⎝⎛i∈Ij∑hi⎠⎞wj2⎦⎤+γ⋅T+λ⋅21j=1∑Twj2+C=j=1∑T⎣⎡⎝⎛i∈Ij∑gi⎠⎞wj+21⎝⎛i∈Ij∑hi+λ⎠⎞wj2⎦⎤+γ⋅T+C
其中第二步是因为不管
L
(
y
i
,
y
^
i
(
t
−
1
)
)
L(y_i,\hat{y}_i^{(t-1)})
L(yi,y^i(t−1))取值是常量,和最后的常量
C
C
C求和结果还是常量(式47的常量
C
C
C和48含义不同,为了方便依然使用
C
C
C),常数不影响优化过程,定义:
G
j
=
∑
i
∈
I
j
g
i
H
j
=
∑
i
∈
I
j
h
i
G_j=\sum_{i\in I_j}g_i\\ H_j=\sum_{i\in I_j}h_i
Gj=i∈Ij∑giHj=i∈Ij∑hi
目标函数:
O
b
j
t
(
f
i
)
≈
∑
j
=
1
T
[
(
∑
i
∈
I
j
g
i
)
w
j
+
1
2
(
∑
i
∈
I
j
h
i
+
λ
)
w
j
2
]
+
γ
⋅
T
+
C
=
∑
j
=
1
T
[
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
]
+
γ
⋅
T
+
C
Obj^{t}(f_i)\approx \sum_{j=1}^T\left[\left(\sum_{i\in I_j} g_i\right)w_j+\frac{1}{2}\left(\sum_{i\in I_j}h_i+\lambda\right)w_j^2\right]+\gamma\cdot T+C\\ =\sum_{j=1}^T\left[G_jw_j+\frac{1}{2}\left(H_j+\lambda\right)w_j^2\right]+\gamma\cdot T+C
Objt(fi)≈j=1∑T⎣⎡⎝⎛i∈Ij∑gi⎠⎞wj+21⎝⎛i∈Ij∑hi+λ⎠⎞wj2⎦⎤+γ⋅T+C=j=1∑T[Gjwj+21(Hj+λ)wj2]+γ⋅T+C
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
G_jw_j+\frac{1}{2}\left(H_j+\lambda\right)w_j^2
Gjwj+21(Hj+λ)wj2求最值。本质上相当于求
a
x
+
1
2
b
x
2
ax+\frac{1}{2}bx^2
ax+21bx2的最值,这样就求得了
x
=
−
a
b
x=-\frac{a}{b}
x=−ba时取的极小值点
−
a
2
2
b
\frac{-a^2}{2b}
2b−a2。
w
j
∗
=
−
G
i
H
j
+
λ
w
∗
为叶子节点的权重
w^*_j=-\frac{G_i}{H_j+\lambda}\quad\text{$w^*$为叶子节点的权重}
wj∗=−Hj+λGiw∗为叶子节点的权重
再回代,就可以把
O
b
j
t
(
f
i
)
Obj^{t}(f_i)
Objt(fi)中的
w
w
w给消去了,得到了
O
b
j
t
(
f
i
)
=
−
1
2
∑
j
=
1
T
G
j
2
H
j
+
λ
+
γ
T
Obj^{t}(f_i)=-\frac{1}{2}\sum_{j=1}^T\frac{G_j^2}{H_j+\lambda}+\gamma T
Objt(fi)=−21j=1∑THj+λGj2+γT
这样我们就把第
t
t
t棵树带来最小损失变成了只与
t
−
1
t-1
t−1相关的一个新的损失函数。
分裂节点
在实际训练过程中,当建立第
t
t
t 棵树时,XGBoost采用贪心法进行树结点的分裂,
从树深为0时开始:
- 对树中的每个叶子结点尝试进行分裂。
- 每次分裂后,原来的一个叶子结点继续分裂为左右两个子叶子结点,原叶子结点中的样本集将根据该结点的判断规则分散到左右两个叶子结点中。
- 新分裂一个结点后,我们需要检测这次分裂是否会给损失函数带来增益,增益的定义如下:
G a i n = O b j L + R − ( O b j L + O b j R ) = − 1 2 ( G L + G R ) 2 H L + H R + λ + γ T − ( − 1 2 G L 2 H L + λ + γ T + 1 2 G R 2 H R + λ + γ T ) = 1 2 [ 1 2 G L 2 H L + λ + 1 2 G R 2 H R + λ − ( G L + G R ) 2 H L + H R + λ ] − γ T Gain = Obj_{L+R}-(Obj_L+Obj_R)\\ =-\frac{1}{2}\frac{(G_L+G_R)^2}{H_L+H_R+\lambda}+\gamma T-(-\frac{1}{2}\frac{G_L^2}{H_L+\lambda}+\gamma T+\frac{1}{2}\frac{G_R^2}{H_R+\lambda}+\gamma T)\\ =\frac{1}{2}\left[\frac{1}{2}\frac{G_L^2}{H_L+\lambda}+\frac{1}{2}\frac{G_R^2}{H_R+\lambda}-\frac{(G_L+G_R)^2}{H_L+H_R+\lambda}\right]-\gamma T Gain=ObjL+R−(ObjL+ObjR)=−21HL+HR+λ(GL+GR)2+γT−(−21HL+λGL2+γT+21HR+λGR2+γT)=21[21HL+λGL2+21HR+λGR2−HL+HR+λ(GL+GR)2]−γT
如果增益 G a i n > 0 Gain>0 Gain>0则分裂为两个叶子节点后,目标函数下降了,此次分裂为有效分裂关键在于如何寻找最佳分割点: - 遍历每个结点的每个特征;
- 对每个特征,按特征值大小将特征值排序;
- 线性扫描,找出每个特征的最佳分裂特征值;
- 在所有特征中找出最好的分裂点(分裂后增益最大的特征及特征值)
上面是一种贪心的方法,每次进行分裂尝试都要遍历一遍全部候选分割点,也叫做全局扫描法。但当数据量过大导致内存无法一次载入或者在分布式情况下,贪心算法的效率就会变得很低,全局扫描法不再适用。基于此,XGBoost提出了一系列加快寻找最佳分裂点的方案: - 特征预排序+缓存:XGBoost在训练之前,预先对每个特征按照特征值大小进行排序,然后保存为block结构,后面的迭代中会重复地使用这个结构,使计算量大大减小。
- 分位点近似法:对每个特征按照特征值排序后,采用类似分位点选取的方式,仅仅选出常数个特征值作为该特征的候选分割点,在寻找该特征的最佳分割点时,从候选分割点中选出最优的一个。
- 并行查找:由于各个特性已预先存储为block结构,XGBoost支持利用多个线程并行地计算每个特征的最佳分割点,这不仅大大提升了结点的分裂速度,也极利于大规模训练集的适应性扩展。
停止条件
树生长的停止条件:
- 当新引入的一次分裂所带来的增益Gain<0时,放弃当前的分裂。
- 当树达到最大深度时,停止建树,因为树的深度太深容易出现过拟合,这里需要设置一个超参数max_depth。
- 当引入一次分裂后,重新计算新生成的左、右两个叶子结点的样本权重和。如果任一个叶子结点的样本权重低于某一个阈值,也会放弃此次分裂。这涉及到一个超参数:最小样本权重和,是指如果一个叶子节点包含的样本数量太少也会放弃分裂,防止树分的太细,这也是过拟合的一种措施。