核心思想
核心为加法模型,优化方法采用前向分步算法,其核心为gbdt的延伸,并且成功的添加了正则项,保证模型的泛化能力强。
推导过程
根据gbdt的公式可得,
f m ( x ) = f m − 1 ( x ) + T ( x ; θ m ) f_m(x)=f_{m-1}(x)+T(x;\theta_m) fm(x)=fm−1(x)+T(x;θm)
确定下一棵决策树的参数的方法如下,
O b j m = ∑ i = 1 N L ( y i , f m − 1 ( x i ) + T ( x i ; θ m ) ) Obj_m=\sum_{i=1}^{N}L(y_i, f_{m-1}(x_i)+T(x_i;\theta_ m)) Objm=i=1∑NL(yi,fm−1(xi)+T(xi;θm))
而xgboost的目标是使如下公式最小,
O
b
j
m
=
∑
i
=
1
N
L
(
y
i
,
f
m
−
1
(
x
i
)
+
T
(
x
i
;
θ
m
)
)
+
Ω
(
T
(
x
;
θ
m
)
)
+
c
o
n
s
t
a
n
t
Obj_m=\sum_{i=1}^{N}L(y_i, f_{m-1}(x_i)+T(x_i;\theta_ m))+\Omega(T(x;\theta _m))+constant
Objm=i=1∑NL(yi,fm−1(xi)+T(xi;θm))+Ω(T(x;θm))+constant
通过泰勒级数展开 f ( x + Δ x ) = f ( x ) + f ′ ( x ) Δ x + 1 2 f ′ ′ ( x ) Δ x 2 + ⋯ f(x+\Delta x)=f(x)+f'(x)\Delta x+\frac{1}{2}f''(x)\Delta x^2+\cdots f(x+Δx)=f(x)+f′(x)Δx+21f′′(x)Δx2+⋯可得,
O
b
j
m
=
∑
i
=
1
N
[
l
(
y
i
,
f
m
−
1
(
x
i
)
)
+
g
i
∗
T
(
x
i
;
θ
m
)
+
1
2
h
i
∗
(
T
(
x
i
;
θ
m
)
)
2
]
+
Ω
(
T
(
x
i
,
θ
m
)
)
+
c
o
n
s
t
a
n
t
Obj_m = \sum_{i=1}^{N}[l(y_i,f_{m-1}(x_i))+g_i*T(x_i;\theta _m)+\frac{1}{2}h_i *(T(x_i;\theta _m))^2]+\Omega (T(x_i,\theta _m))+constant
Objm=i=1∑N[l(yi,fm−1(xi))+gi∗T(xi;θm)+21hi∗(T(xi;θm))2]+Ω(T(xi,θm))+constant
其中
{ g i = ∂ l ( y i , f m − 1 ( x i ) ) ∂ f m − 1 ( x i ) h i = ∂ 2 l ( y i , f m − 1 ( x i ) ) ∂ ( f m − 1 ( x i ) ) 2 \left\{\begin{matrix} g_i = \frac{\partial l(y_i, f_{m-1}(x_i))}{\partial f_{m-1}(x_i)}\\ h_i = \frac{\partial^2 l(y_i, f_{m-1}(x_i))}{\partial (f_{m-1}(x_i))^2} \end{matrix}\right. {gi=∂fm−1(xi)∂l(yi,fm−1(xi))hi=∂(fm−1(xi))2∂2l(yi,fm−1(xi))
而 l ( y i , f m − 1 ( x i ) ) l(y_i,f_{m-1}(x_i)) l(yi,fm−1(xi))在第m轮训练时被看成了常数,因为 , f m − 1 ( x i ) ,f_{m-1}(x_i) ,fm−1(xi)和 y i y_i yi都已知,因而目标变为了如下公式,
O b j m = ∑ i = 1 N [ g i ∗ T ( x i ; θ m ) + 1 2 h i ∗ ( T ( x i ; θ m ) ) 2 ] + Ω ( T ( x i , θ m ) ) Obj_m = \sum_{i=1}^{N}[g_i*T(x_i;\theta _m)+\frac{1}{2}h_i *(T(x_i;\theta _m))^2]+\Omega (T(x_i,\theta _m)) Objm=i=1∑N[gi∗T(xi;θm)+21hi∗(T(xi;θm))2]+Ω(T(xi,θm))
这里,为了方便,把上述的 T ( x i , θ m ) T(x_i,\theta _m) T(xi,θm)变为 T m ( x i ) T_m(x_i) Tm(xi)来表示,在这里我们需要对 T m ( x i ) T_m(x_i) Tm(xi)做出一个定义,
T
m
(
x
)
=
w
q
(
x
)
w
∈
R
T
,
q
:
R
d
→
{
1
,
2
,
.
.
.
,
J
}
T_m(x)=w_{q(x)} \quad w\in R^T, \quad q:R^d\rightarrow \left \{ 1,2,...,J \right \}
Tm(x)=wq(x)w∈RT,q:Rd→{1,2,...,J}
w代表的是树中树叶的权重,q代表的是树的结构,J代表树的叶子节点个数,这时定义树的复杂度如下,
Ω ( T m ) = γ J + 1 2 λ ∑ j = 1 J w j 2 \Omega(T_m)=\gamma J +\frac{1}{2}\lambda \sum_{j=1}^{J}w_{j}^{2} Ω(Tm)=γJ+21λj=1∑Jwj2
定义第j个节点中数据子集的编号为如下 I j = { i ∣ q ( x i ) = j } I_j=\{i|q(x_i)=j\} Ij={i∣q(xi)=j},对之前的目标函数重新表达可得,
O b j m = ∑ i = 1 N [ g i ∗ T ( x i ; θ m ) + 1 2 h i ∗ ( T ( x i ; θ m ) ) 2 ] + Ω ( T ( x i , θ m ) ) = ∑ i = 1 N [ g i w q ( x i ) + 1 2 h i ∗ w q ( x i ) 2 ] + γ J + 1 2 λ ∑ j = 1 J w j 2 = ∑ j = 1 J [ ( ∑ i ∈ I j g i ) w j + 1 2 ∑ i ∈ I j h i w j 2 ] + γ J + 1 2 λ ∑ j = 1 J w j 2 = ∑ j = 1 J [ ( ∑ i ∈ I j g i ) w j + 1 2 ( ∑ i ∈ I j h i + λ ) w j 2 ] + γ J \begin{matrix} Obj_m = \sum_{i=1}^{N}[g_i*T(x_i;\theta _m)+\frac{1}{2}h_i *(T(x_i;\theta _m))^2]+\Omega (T(x_i,\theta _m))\\ =\sum_{i=1}^{N}[g_i w_{q(x_i)}+\frac{1}{2}h_i *w_{q(x_i)}^{2}]+\gamma J+\frac{1}{2}\lambda \sum_{j=1}^{J}w_{j}^{2}\\ =\sum_{j=1}^{J}[(\sum _{i\in I_j}g_i)w_j+\frac{1}{2}\sum _{i\in I_j}h_iw_{j}^{2}]+\gamma J+\frac{1}{2}\lambda \sum _{j=1}^J w_{j}^{2}\\ =\sum_{j=1}^{J}[(\sum _{i\in I_j}g_i)w_j+\frac{1}{2}(\sum _{i\in I_j}h_i+\lambda )w_{j}^{2}]+\gamma J \end{matrix} Objm=∑i=1N[gi∗T(xi;θm)+21hi∗(T(xi;θm))2]+Ω(T(xi,θm))=∑i=1N[giwq(xi)+21hi∗wq(xi)2]+γJ+21λ∑j=1Jwj2=∑j=1J[(∑i∈Ijgi)wj+21∑i∈Ijhiwj2]+γJ+21λ∑j=1Jwj2=∑j=1J[(∑i∈Ijgi)wj+21(∑i∈Ijhi+λ)wj2]+γJ
上述公式的意义在于把所有样本加和的公式转变为所有树的加和公式,对于上述最后的公式求最小值,其实是一个简单的二次项求极小值的过程,
a r g m i n x ( G x + 1 2 H x 2 ) = − G H , H > 0 m i n x ( G x + 1 2 H x 2 ) = − 1 2 G 2 H argmin_x (Gx+\frac{1}{2}Hx^2)=-\frac{G}{H}, H>0 \quad min_x(Gx+\frac{1}{2}Hx^2)=-\frac{1}{2}\frac{G^2}{H} argminx(Gx+21Hx2)=−HG,H>0minx(Gx+21Hx2)=−21HG2
设 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∈Ijgi,Hj=∑i∈Ijhi,可得如下公式,
O
b
j
m
=
∑
j
=
1
J
[
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
]
+
γ
J
Obj_m=\sum_{j=1}^{J}[G_j w_j+\frac{1}{2}(H_j+\lambda )w_j^2]+\gamma J
Objm=j=1∑J[Gjwj+21(Hj+λ)wj2]+γJ
假设现在树的结构定下,那么最优解如下。
w j ∗ = − G j H j + λ O b j = − 1 2 ∑ j = 1 J G j 2 H j + λ + γ J w_j^*=-\frac{G_j}{H_j +\lambda } \quad Obj = -\frac{1}{2}\sum_{j=1}^{J}\frac{G_j^2}{H_j+\lambda }+\gamma J wj∗=−Hj+λGjObj=−21j=1∑JHj+λGj2+γJ
对于算法的时间复杂度,遍历每一层(这里的每一层指的是树上同一深度的节点)时,对于每个feature,都有会进行一次快速排序,因而时间复杂度为 O ( N ∗ l o g ( N ) ) O(N*log(N)) O(N∗log(N)), 这里的N为样本总个数,而一共有d个feature,因而遍历一层需要的时间为 O ( d ∗ N ∗ l o g ( N ) ) O(d*N*log(N)) O(d∗N∗log(N)),树平均有K层,那么一个树训练完成后总的时间复杂度为 K ∗ d ∗ N ∗ l o g ( N ) K*d*N*log(N) K∗d∗N∗log(N)。
拓展之近似算法
上述方法中最核心的内容为如何分裂节点,最先想到的是暴力搜索,就是针对每个特征以及每个特征的所有可能取值,都去计算一遍Gain,得到最大者分裂,在对某一个特征计算Gain的时候需要先把数据按照这一维数据的大小排序,这样操作会让算法运行的更有效,但是问题是如果说数据量太大或者电脑的内存不够,不支持这么庞大的计算,论文作者就引入了近似算法的概念。
算法的核心在于对于某一个特征,不去遍历所有可能的值作为分裂值,而只是选择最有可能成为最优分裂值的子集作为分裂值的候选者,因而算法要比之前快很多。
首先,对于数据集的第k个特征,有如下数据集
D
k
=
{
(
x
1
k
,
h
1
)
,
(
x
2
k
,
h
2
)
,
.
.
.
,
(
x
n
k
,
h
n
)
}
D_k=\{(x_{1k}, h_1), (x_{2k}, h_2), ..., (x_{nk}, h_n)\}
Dk={(x1k,h1),(x2k,h2),...,(xnk,hn)},定义一个排序函数,
r
k
:
R
↦
[
0
,
+
∞
)
r_k:R \mapsto [0,+ \infty)
rk:R↦[0,+∞),
r
k
(
z
)
=
1
∑
(
x
,
h
)
∈
D
k
h
∑
(
x
,
h
)
∈
D
k
,
x
<
z
h
r_k(z)=\frac{1}{\sum_{(x,h)\in D_k}h}\sum_{(x,h)\in D_k, x<z}h
rk(z)=∑(x,h)∈Dkh1(x,h)∈Dk,x<z∑h
对于上述问题,找到一系列候选值,
∣
r
k
(
s
k
,
j
)
−
r
k
(
s
k
,
j
+
1
)
∣
<
ε
,
s
k
1
=
m
i
n
i
x
i
k
,
s
k
l
=
m
a
x
i
x
i
k
|r_k(s_{k,j})-r_k(s_{k,j+1})|<\varepsilon, \quad s_{k1}=min_i x_{ik}, s_{kl}=max_i x_{ik}
∣rk(sk,j)−rk(sk,j+1)∣<ε,sk1=minixik,skl=maxixik
其中
ε
\varepsilon
ε是一个近似值,从这里可以知道会产生
1
ε
\frac{1}{\varepsilon }
ε1个候选值,而且每个值都赋予了
h
i
h_i
hi的权重,可以从下式中得到答案,
O
b
j
m
=
∑
i
=
1
N
1
2
h
i
(
f
t
(
x
i
)
−
g
i
h
i
)
2
+
Ω
(
T
m
)
+
c
o
n
s
t
a
n
t
Obj_m = \sum_{i=1}^{N}\frac{1}{2}h_i (f_t(x_i)-\frac{g_i}{h_i})^2+\Omega(T_m)+constant
Objm=i=1∑N21hi(ft(xi)−higi)2+Ω(Tm)+constant
这就是最初目标函数的变形,可以看出,每个样本被赋予了
h
i
h_i
hi的权重,这样再通过这些候选点把样本按照桶排序的方法把相近的数据放入一个桶中,再逐桶计算
G
G
G和
H
H
H,而后在这个基础上来选取最优分裂值。
拓展之block储存加速
算法大量的时间消耗在对数据的排序上面,而论文的做法是先对每个feature进行排序,并记录排序后每个数据指向其原始梯度的指针,而后把所有排好序的feature放在一起组成一个新的数据,这样每个数据都能够根据记录的指针找到其原始的梯度,这样再对feature进行线性寻找最佳分裂值时不用每次都重新排一次序了,从而大大提升算法的时间。
xgboost VS gbdt
- 传统GBDT以CART作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。
- 传统GBDT在优化时只用到一阶导数信息,xgboost则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数。顺便提一下,xgboost工具支持自定义代价函数,只要函数可一阶和二阶求导。
- xgboost在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和。从Bias-variance tradeoff角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,防止过拟合,这也是xgboost优于传统GBDT的一个特性。
- 对缺失值的处理。对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向,缺失值数据会被分到左子树和右子树分别计算损失,选择较优的那一个;如果训练中没有数据缺失,预测时出现了数据缺失,那么默认被分类到右子树。
- 实现了一种分裂节点寻找的近似算法,用于加速和减小内存消耗。
- data事先对于每一个feature都排好序并以block的形式存储,利于并行计算。