在网上看了xgboost的介绍,很多博客一开始并没有看的很明白,于是我按照自己的理解写一下xgboost的原理。
主要参考了:
https://xgboost.readthedocs.io/en/latest/tutorials/model.html (英文详细教程)
https://www.zhihu.com/question/41354392/answer/98658997 (很有用的PPT,出自wepon大神)
https://www.jianshu.com/p/7e0e2d66b3d4 (实战xgboost)
1. Xgboost的模型
xgboost的模型为:
y
i
^
=
ϕ
(
x
i
)
=
∑
k
=
1
K
f
k
(
x
i
)
,
f
k
ϵ
F
,
\hat{y_{i}}=\phi \left ( x_{i} \right )=\sum_{k=1}^{K}f_{k}\left ( x_{i} \right ),f_{k}\epsilon F,
yi^=ϕ(xi)=k=1∑Kfk(xi),fkϵF,
这是个加法模型,由k个弱分类器一起来决定输入
x
i
x_{i}
xi的输出的结果
y
i
y_{i}
yi,其中每一个弱分类器
f
i
(
x
)
f_{i}\left ( x \right )
fi(x)是一颗决策树。这个决策树
f
i
(
x
)
f_{i}\left ( x \right )
fi(x)的每一个叶子节点都对应一个分数,每个样本
x
i
x_{i}
xi经过这颗决策树
f
i
(
x
)
f_{i}\left ( x \right )
fi(x)的规则分类之后都落在一个叶子节点上 ,得到一个分数,如下图所示:(这里一共5个样本,每个样本最后都会分到叶子节点,获得对应的分数)
这颗决策树可以由以下模型来表示:
f
(
x
)
=
w
q
(
x
)
(
q
:
R
m
→
T
,
w
∈
R
T
)
f\left ( x \right )=w_{q\left ( x \right )}\left ( q:\mathbb{R}^{m}\rightarrow T,w\in \mathbb{R}^{T} \right )
f(x)=wq(x)(q:Rm→T,w∈RT)
其中
q
(
x
)
q(x)
q(x)表示表示将样本
x
x
x分到了某个叶子节点
i
i
i上,
w
w
w则是叶子节点
i
i
i对应的分数
w
i
w_{i}
wi,如上图红色和蓝色的标记所示,所以
w
q
(
x
)
w_{q\left ( x \right )}
wq(x) 表示回归树对样本
x
x
x的预测值。
2. 目标函数
xgboost的目标函数为:
O
b
j
=
∑
i
n
l
(
y
^
i
,
y
i
)
+
∑
k
K
Ω
(
f
k
)
Obj=\sum_{i}^{n} l(\hat{y}_{i},y_{i})+\sum_{k}^{K}\Omega (f_{k})
Obj=i∑nl(y^i,yi)+k∑KΩ(fk)
一共有n个训练样本,K颗树。并且在目标函数中,加入了正则化,对每棵回归树的复杂度进行了惩罚
∑
k
K
Ω
(
f
k
)
\sum_{k}^{K}\Omega (f_{k})
∑kKΩ(fk),使得学习出来的模型更加不容易过拟合。
因为xgboost的模型是个加法模型,在初始化(第0次迭代)的时候呢,模型是:
y
^
i
(
0
)
=
0
\hat{y}_{i}^{(0)}=0
y^i(0)=0
第1次迭代:
y
^
i
(
1
)
=
f
1
(
x
i
)
=
y
^
i
(
0
)
+
f
1
(
x
i
)
\hat{y}_{i}^{(1)}=f_{1}(x_{i})=\hat{y}_{i}^{(0)}+f_{1}(x_{i})
y^i(1)=f1(xi)=y^i(0)+f1(xi)
第2次迭代:
y
^
i
(
2
)
=
f
1
(
x
i
)
+
f
2
(
x
i
)
=
y
^
i
(
1
)
+
f
2
(
x
i
)
\hat{y}_{i}^{(2)}=f_{1}(x_{i})+f_{2}(x_{i})=\hat{y}_{i}^{(1)}+f_{2}(x_{i})
y^i(2)=f1(xi)+f2(xi)=y^i(1)+f2(xi)
第t次迭代:
y
^
i
(
t
)
=
∑
k
=
1
t
f
k
(
x
i
)
=
y
^
i
(
t
−
1
)
+
f
t
(
x
i
)
\hat{y}_{i}^{(t)}=\sum_{k=1}^{t}f_{k}\left ( x_{i} \right )=\hat{y}_{i}^{(t-1)}+f_{t}(x_{i})
y^i(t)=k=1∑tfk(xi)=y^i(t−1)+ft(xi)
替换掉目标函数中的
y
^
i
(
t
)
\hat{y}_{i}^{(t)}
y^i(t),即在第t次迭代的时候的目标函数,我们通过这个目标函数学习
f
t
(
x
i
)
f_{t}(x_{i})
ft(xi):
O
b
j
=
∑
i
n
l
(
y
i
,
y
^
i
(
t
−
1
)
+
f
t
(
x
i
)
)
+
Ω
(
f
k
)
Obj=\sum_{i}^{n} l(y_{i},\hat{y}_{i}^{(t-1)}+f_{t}(x_{i}))+\Omega (f_{k})
Obj=i∑nl(yi,y^i(t−1)+ft(xi))+Ω(fk)
在上式中,
y
i
y_{i}
yi是训练数据的标签,已知的;
y
^
i
(
t
−
1
)
\hat{y}_{i}^{(t-1)}
y^i(t−1)在上一步迭代t-1中也已经求得,只需要学习
f
t
(
x
i
)
f_{t}(x_{i})
ft(xi)。因为只需要学习
f
t
(
x
i
)
f_{t}(x_{i})
ft(xi),所以
∑
k
K
Ω
(
f
k
)
\sum_{k}^{K}\Omega (f_{k})
∑kKΩ(fk)被
Ω
(
f
k
)
\Omega (f_{k})
Ω(fk)替换了。
下面到了xgboost的一个关键步骤,将目标函数在 y ^ i ( t − 1 ) \hat{y}_{i}^{(t-1)} y^i(t−1)进行二阶泰勒展开:
- 复习泰勒公式展开: f ( x + Δ x ) ≃ f ( x ) + f ′ ( x ) Δ x + 1 2 f ′ ′ ( x ) Δ x 2 f(x+\Delta x)\simeq f(x)+f^{'}(x)\Delta x+\frac{1}{2}f^{''}(x)\Delta x^{2} f(x+Δx)≃f(x)+f′(x)Δx+21f′′(x)Δx2
令目标函数
O
b
j
Obj
Obj中
y
^
i
(
t
)
\hat{y}_{i}^{(t)}
y^i(t)为
x
x
x,
f
t
(
x
i
)
f_{t}(x_{i})
ft(xi)为
Δ
x
\Delta x
Δx,则二阶泰勒展开之后目标函数变为:
O
b
j
≃
∑
i
n
[
l
(
y
i
,
y
^
i
(
t
−
1
)
)
+
g
i
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
]
+
Ω
(
f
k
)
Obj\simeq \sum_{i}^{n} [l(y_{i},\hat{y}_{i}^{(t-1)})+g_{i}f_{t}(x_{i})+\frac{1}{2}h_{i}f_{t}^{2}(x_{i})]+\Omega (f_{k})
Obj≃i∑n[l(yi,y^i(t−1))+gift(xi)+21hift2(xi)]+Ω(fk)
- g i g_{i} gi是 l ( y i , y ^ i ( t − 1 ) ) l(y_{i},\hat{y}_{i}^{(t-1)}) l(yi,y^i(t−1))的一阶倒数: g i = ∂ y ^ ( t − 1 ) l ( y i , y ^ t − 1 ) g_{i}=\partial _{\hat{y}^{(t-1)}}l(y_{i},\hat{y}^{t-1}) gi=∂y^(t−1)l(yi,y^t−1)
- h i h_{i} hi是 l ( y i , y ^ i ( t − 1 ) ) l(y_{i},\hat{y}_{i}^{(t-1)}) l(yi,y^i(t−1))的二阶倒数: h i = ∂ y ^ ( t − 1 ) 2 l ( y i , y ^ t − 1 ) h_{i}=\partial_{\hat{y}^{(t-1)}}^{2}l(y_{i},\hat{y}^{t-1}) hi=∂y^(t−1)2l(yi,y^t−1)
去掉公式中的常数项:
O
b
j
≃
∑
i
n
[
g
i
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
]
+
Ω
(
f
k
)
Obj\simeq \sum_{i}^{n} [g_{i}f_{t}(x_{i})+\frac{1}{2}h_{i}f_{t}^{2}(x_{i})]+\Omega (f_{k})
Obj≃i∑n[gift(xi)+21hift2(xi)]+Ω(fk)
3. 决策树的复杂度
在第1节的时候介绍过,决策树的模型是
f
(
x
)
=
w
q
(
x
)
(
q
:
R
m
→
T
,
w
∈
R
T
)
f\left ( x \right )=w_{q\left ( x \right )}\left ( q:\mathbb{R}^{m}\rightarrow T,w\in \mathbb{R}^{T} \right )
f(x)=wq(x)(q:Rm→T,w∈RT),xgboost定义决策树的复杂度公式
Ω
(
f
k
)
\Omega (f_{k})
Ω(fk)为:
Ω
(
f
k
)
=
γ
T
+
1
2
λ
∥
w
∥
2
\Omega (f_{k})=\gamma T+\frac{1}{2}\lambda \left \| w \right \|^{2}
Ω(fk)=γT+21λ∥w∥2
其中:
- T T T为决策树的叶子节点的个数
-
∥
w
∥
2
\left \| w \right \|^{2}
∥w∥2为叶子节点得分L2正则化项,针对每个叶结点的得分增加L2平滑,目的也是为了避免过拟合
4. 再回到目标函数
将
f
(
x
)
=
w
q
(
x
)
f\left ( x \right )=w_{q\left ( x \right )}
f(x)=wq(x) 和
Ω
(
f
k
)
\Omega (f_{k})
Ω(fk)代入目标函数:
O
b
j
≃
∑
i
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
Obj\simeq \sum_{i}^{n} [g_{i}w_{q(x_{i})}+\frac{1}{2}h_{i}w_{q(x_{i})}^{2}]+\gamma T+\frac{1}{2}\lambda \sum_{j=1}^{T}w_{j}^{2}
Obj≃i∑n[giwq(xi)+21hiwq(xi)2]+γT+21λj=1∑Twj2
公式中
T
T
T是指决策树的
T
T
T个叶子节点。
定义每个叶子节点
j
j
j上的样本集合为:
I
j
=
{
i
∣
q
(
x
i
=
j
)
}
I_{j}=\left \{ i|q(x_{i}=j) \right \}
Ij={i∣q(xi=j)}
则目标函数可以写成按叶子节点累加的形式:
O
b
j
=
∑
j
=
1
T
[
(
∑
i
ϵ
I
j
g
j
)
w
j
+
1
2
(
∑
i
ϵ
I
j
h
i
+
λ
)
w
j
2
]
+
γ
T
=
∑
j
=
1
T
[
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
]
+
γ
T
Obj=\sum_{j=1}^{T}\left [ (\sum _{i\epsilon I_{j}}g_{j})w_{j}+\frac{1}{2}(\sum _{i\epsilon I_{j}}h_{i}+\lambda )w_{j}^{2} \right ]+\gamma T =\sum_{j=1}^{T}\left [ G_{j}w_{j}+\frac{1}{2}(H_{j}+\lambda )w_{j}^{2} \right ]+\gamma T
Obj=j=1∑T⎣⎡(iϵIj∑gj)wj+21(iϵIj∑hi+λ)wj2⎦⎤+γT=j=1∑T[Gjwj+21(Hj+λ)wj2]+γT
- G j = ∑ i ϵ I j g j G_{j}=\sum _{i\epsilon I_{j}}g_{j} Gj=∑iϵIjgj 对于落入决策树第 i i i个叶子节点的样本,计算它们的 g i = ∂ y ^ ( t − 1 ) l ( y i , y ^ t − 1 ) g_{i}=\partial _{\hat{y}^{(t-1)}}l(y_{i},\hat{y}^{t-1}) gi=∂y^(t−1)l(yi,y^t−1)并累加
- H j = ∑ i ϵ I j h i H_{j}=\sum _{i\epsilon I_{j}}h_{i} Hj=∑iϵIjhi 对于落入决策树第 i i i个叶子节点的样本,计算它们的 h i = ∂ y ^ ( t − 1 ) 2 l ( y i , y ^ t − 1 ) h_{i}=\partial_{\hat{y}^{(t-1)}}^{2}l(y_{i},\hat{y}^{t-1}) hi=∂y^(t−1)2l(yi,y^t−1)并累加
5. 求解第t次迭代的决策树 f t ( x i ) f_{t}(x_{i}) ft(xi)
有了上述的目标函数之后,我们是怎么得出第t次迭代的决策树
f
t
(
x
i
)
f_{t}(x_{i})
ft(xi)的呢?
我们先来看看
f
t
(
x
i
)
f_{t}(x_{i})
ft(xi)都有哪些是需要我们求的:
- 树的结构: q ( x ) q(x) q(x)
- 叶子节点对于的预测分数: w w w
5.1 叶子节点对于的预测分数: w w w
我们先来看看
w
w
w是如何确定的。
假设树的的结构
q
(
x
)
q(x)
q(x)确定了,为了使得目标函数最小,可以令目标函数为0,解得每个叶子节点的最优预测分数为:
w
j
∗
=
−
G
j
H
j
+
λ
w_{j}^{*}=-\frac{G_{j}}{H_{j}+\lambda }
wj∗=−Hj+λGj
代入目标函数,得到最小的损失为:
L
~
∗
=
−
1
2
∑
j
=
1
T
G
j
2
H
j
+
λ
+
γ
T
\tilde{L}^{*}=-\frac{1}{2}\sum_{j=1}^{T}\frac{G_{j}^{2}}{H_{j}+\lambda }+\gamma T
L~∗=−21j=1∑THj+λGj2+γT
5.2 树的结构 q ( x ) q(x) q(x)
5.1是假设树的结构确定了求
w
w
w,但是现在树的结构怎么求呢?
xgboost使用贪心算,每次分裂一个节点,计算分裂前后的增益,选择增益最大的。
那么这个增益怎么算?我们再来看看上面求出的最小的损失
L
~
∗
=
−
1
2
∑
j
=
1
T
G
j
2
H
j
+
λ
+
γ
T
\tilde{L}^{*}=-\frac{1}{2}\sum_{j=1}^{T}\frac{G_{j}^{2}}{H_{j}+\lambda }+\gamma T
L~∗=−21∑j=1THj+λGj2+γT,其中有一项是
G
j
2
H
j
+
λ
\frac{G_{j}^{2}}{H_{j}+\lambda }
Hj+λGj2,这一项的值越大,最小的损失
L
~
∗
\tilde{L}^{*}
L~∗就越小,因为这一项的符号是负号。
于是,如果在某个叶子节点处进行分裂,将这个叶子节点变成左右子树,样本落到左子树,上述的一项公式的值记为
G
L
2
H
L
+
λ
\frac{G_{L}^{2}}{H_{L}+\lambda }
HL+λGL2,右子树的值记为
G
R
2
H
R
+
λ
\frac{G_{R}^{2}}{H_{R}+\lambda }
HR+λGR2,原未分裂的叶子节点的值记为
(
G
L
+
G
R
)
2
H
L
+
H
R
+
λ
\frac{(G_{L}+G_{R})^{2}}{H_{L}+H_{R}+\lambda }
HL+HR+λ(GL+GR)2,所以分裂前后的增益定义为:
G
a
i
n
=
G
L
2
H
L
+
λ
+
G
R
2
H
R
+
λ
−
(
G
L
+
G
R
)
2
H
L
+
H
R
+
λ
−
γ
Gain=\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 }-\gamma
Gain=HL+λGL2+HR+λGR2−HL+HR+λ(GL+GR)2−γ
增益
G
a
i
n
Gain
Gain越大,说明在这个叶子节点进行分裂,损失函数会越小。所以在一开始的时候循环所有的特征的所有的值,选取
G
a
i
n
Gain
Gain最大的节点进行分裂,然后再对左子树右子树分别进行分裂。大概的思想是:
Gain=0
for i=1 to 所有的特征
for j=1 to 第i个特征的所有的值
计算Gain,保存最大的Gain的值的i和j
具体的精确算法:
遍历所有特征的所有可能的分割点,计算gain值,选取值最大的(feature,value)去分割。此外,xgboost算法设计对特征进行了排序,分位点划分等细节。
通过此方法生成每一轮迭代新生成的树的结构
q
(
x
)
q(x)
q(x)
以上就是xgboost的预测模型和实现的原理,是我个人的理解,里面还有各种细节还需要去查看xgboost的原文和别的博客的介绍。