我们都知道决策树有个明显的缺点就是容易过拟合,树的深度不容易控制,同时其表达能力有限,容易受数据的影响稳定性差,那么如何在不改变原始模型的基础上进一步提高模型性能呢?有两个思路:一种是采用随机森林的方法,即bagging思想;另一种就是XGBoost方法,boosting思想。
XGBoost可以认为是GBDT的改进和升级,其算法思路相似,实现过程不同,本篇我会以XGB的总结为主,并点出XGBoost与GBDT的不同。
集成学习1——XGBoost
集成学习2——XGBoost本身的特点,及XGB与GBDT、LGB、RF的区别于联系
1, 概述
XGBoost是一种集成学习方法,采用了Boosting思想,XGBoost通过减少残差的方式迭代优化损失函数。假设我们前一轮迭代得到的强学习器是 f t − 1 ( x ) f_{t-1}(x) ft−1(x),与之对应的损失函数是 L ( y , f t − 1 ( x ) ) L(y, f_{t-1}(x)) L(y,ft−1(x)),那么本轮迭代的目标就是找到一个CART树模型的弱学习器 h t ( x ) h_t(x) ht(x),让本轮的损失函数 L ( y , f t ( x ) ) = L ( y , f t − 1 ( x ) + h t ( x ) ) L(y,ft(x))=L(y,ft−1(x)+ht(x)) L(y,ft(x))=L(y,ft−1(x)+ht(x))最小,其实就是以 L ( y , f t − 1 ( x ) ) L(y, f_{t-1}(x)) L(y,ft−1(x))为目标进行优化,让样本的损失函数变得更小。举个例子,如果目标为10,我们第一轮CART树模型预测得到6,那么与目标相差4,第二轮建模就要以4为目标,预测结果为3,那么loss为1,与目标相差为1,继续迭代往下建模减少残差。
好了,下面我们详细推导下XGB的实现过程。
2, XGBoost原理
2.1 获取目标函数
理解任何一种算法模型,都得要从目标函数开始,XGB也不例外。获取目标函数之前,我先看下预测值的表示方法。
XGBoost可以表示成由k个基础模型组成的加法运算:
y ^ i = ∑ k = 1 K f k ( x i ) , f k ∈ F \hat{y}_i = \sum_{k=1}^K f_k(x_i),f_k \in F y^i=k=1∑Kfk(xi),fk∈F
y ^ \hat{y} y^表示预测结果,F表示所有基模型的函数空间。那么一般化的损失函数就是预测值与真实值之间的关系,对于n个样本而言,我们的loss可以写成:
L = ∑ i = 1 n l ( y i , y ^ i ) L=\sum_{i=1}^nl(y_i,\hat{y}_i) L=i=1∑nl(yi,y^i)
我们知道好的模型要平衡偏差与方差,我们最小化损失函数就是在减小偏差,但是模型也要兼顾方差,提高模型对数据波动的抗干扰能力,这里我们得加入正则。
L = ∑ i = 1 n l ( y i , y ^ i ) + ∑ k = 1 K Ω ( f k ) L=\sum_{i=1}^nl(y_i,\hat{y}_i) + \sum_{k=1}^K\Omega(f_k) L=i=1∑nl(yi,y^i)+k=1∑KΩ(fk)
Ω \Omega Ω表示模型的复杂度,这里树的深度和叶子节点的数量都可以表示模型的复杂程度,所以在后面我们会看到xgb有两个正则项,一个是关于预测结果的正则,一个是关于叶子节点数量的正则。
2.2 分解建模过程
目标函数有了,我们看下boosting过程是如何前向传播的,如何逐个建立基础模型的:
y ^ i 0 = 0 y ^ i 1 = f 1 ( x i ) = y ^ i 0 + f 1 ( x i ) y ^ i 2 = f 1 ( x i ) + f 2 ( x i ) = y ^ i 1 + f 2 ( x i ) . . . y ^ i t = ∑ k = 1 t f k ( x i ) = y ^ i t − 1 + f t ( x i ) \begin{aligned} &\hat{y}_i^0=0\\ &\hat{y}_i^1=f_1(x_i)=\hat{y}_i^0 + f_1(x_i)\\ &\hat{y}_i^2 = f_1(x_i) + f_2(x_i) = \hat{y}_i^1 + f_2(x_i)\\ &...\\ &\hat{y}_i^t = \sum_{k=1}^tf_k(x_i)=\hat{y}_i^{t-1} + f_t(x_i) \end{aligned} y^i0=0y^i1=f1(xi)=y^i0+f1(xi)y^i2=f1(xi)+f2(xi)=y^i1+f2(xi)...y^it=k=1∑tfk(xi)=y^it−1+ft(xi)
我们可以看到模型每迭代一次,就会建立一个基础模型,预测结果就会更新一次。
**那么在每一步如何学习一个新的模型呢?**为了不失一般性,我们以第t步,第i个样本的预测结果为例:
y
^
i
t
=
y
^
i
t
−
1
+
f
t
(
x
i
)
\hat{y}_i^t = \hat{y}_i^{t-1}+ f_t(x_i)
y^it=y^it−1+ft(xi)
O
b
j
(
t
)
=
∑
i
=
1
n
l
(
y
i
,
y
^
i
t
)
+
∑
i
=
i
t
Ω
(
f
i
)
=
∑
i
=
1
n
l
(
y
i
,
y
^
i
t
+
f
t
(
x
i
)
)
+
∑
i
=
i
t
Ω
(
f
i
)
+
c
o
n
s
t
a
n
t
\begin{aligned}Obj^{(t)} &=\sum_{i=1}^nl(y_i,\hat{y}_i^t)+ \sum_{i=i}^t\Omega(f_i)\\ &=\sum_{i=1}^nl(y_i,\hat{y}_i^t+f_t(x_i))+ \sum_{i=i}^t\Omega(f_i)+constant \end{aligned}
Obj(t)=i=1∑nl(yi,y^it)+i=i∑tΩ(fi)=i=1∑nl(yi,y^it+ft(xi))+i=i∑tΩ(fi)+constant
此时最优化目标函数,就能求的 f t ( x i ) f_t(x_i) ft(xi),即当前基础模型的优化目标值。
2.3 优化基础模型
这个函数该如何优化呢?我们需要对其换一种表达方式:泰勒展开.
f
(
x
+
Δ
x
)
≈
f
(
x
)
+
f
′
(
x
)
Δ
x
+
1
2
f
′
′
(
x
)
Δ
x
2
f(x+\Delta x)\approx 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
泰勒二阶展开可以近似表示原函数,前文中,当前树的预测结果
f
t
(
x
i
)
f_t(x_i)
ft(xi)就是这里的
Δ
x
\Delta_x
Δx,大家细细品味:
O
b
j
(
t
)
=
∑
i
=
1
n
[
l
(
y
i
,
y
^
i
t
)
+
g
i
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
]
+
Ω
(
f
t
)
+
c
o
n
s
t
a
n
t
Obj^{(t)} = \sum_{i=1}^n[l(y_i,\hat{y}_i^t)+g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)]+ \Omega(f_t)+constant
Obj(t)=i=1∑n[l(yi,y^it)+gift(xi)+21hift2(xi)]+Ω(ft)+constant
假设loss是平方差,那么:
g i = ∂ y ^ i t − 1 ( y ^ i t − 1 − y i ) h i = ∂ y ^ i t − 1 2 ( y ^ i t − 1 − y i ) 2 \begin{aligned} &g_i=\partial_{\hat{y}_i^{t-1}}(\hat{y}_i^{t-1}-y_i)\\ &h_i=\partial_{\hat{y}_i^{t-1}}^2(\hat{y}_i^{t-1}-y_i)^2 \end{aligned} gi=∂y^it−1(y^it−1−yi)hi=∂y^it−12(y^it−1−yi)2
目标函数表示为:
O b j ( t ) = ∑ i = 1 n [ g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ] + Ω ( f t ) Obj^{(t)} = \sum_{i=1}^n[g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)]+ \Omega(f_t) Obj(t)=i=1∑n[gift(xi)+21hift2(xi)]+Ω(ft)
注意:这里的形式仍然是以样本i为基本元素的,每棵树都有多个叶子节点,我们将叠加元素替换为叶子节点预测值w(其实就是预测值f(x)).
O b j ( t ) ≈ ∑ i = 1 n [ g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ] + Ω ( f t ) = ∑ 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 = ∑ j = 1 T [ ( ∑ i ∈ I j g i ) w j + 1 2 ( ∑ i ∈ I j h i + λ ) w j 2 ] + γ T \begin{aligned}Obj^{(t)} &\approx \sum_{i=1}^n[g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)]+ \Omega(f_t)\\ & =\sum_{i=1}^{n}[g_i w_{q(x_i)} + \frac{1}{2}h_iw_{q(x_i)}^2]+\gamma T + \frac{1}{2}\lambda \sum_{j=1}^{T}w_j^2 \\ &=\sum_{j=1}^T[(\sum_{i\in I_j}g_i)w_j + \frac{1}{2}(\sum_{i\in I_j}h_i + \lambda)w_j^2] +\gamma T \end{aligned} Obj(t)≈i=1∑n[gift(xi)+21hift2(xi)]+Ω(ft)=i=1∑n[giwq(xi)+21hiwq(xi)2]+γT+21λj=1∑Twj2=j=1∑T[(i∈Ij∑gi)wj+21(i∈Ij∑hi+λ)wj2]+γT
j是叶子节点的索引,T是叶子节点数目。从节点预测值、节点数目两个方面约束模型,并将基础元素从样本i替换为叶子节点j,那么此目标函数可以理解为:当前树所有叶子节点上,每个样本的目标值加和。其中xi的目标值用loss函数的一阶和二阶导数表示。
我们来定义:
G j = ∑ i ∈ I j g i H j = ∑ i ∈ I j h i \begin{aligned} G_j & =\sum_{i\in I_j}g_i\\ H_j & =\sum_{i\in I_j}h_i \end{aligned} GjHj=i∈Ij∑gi=i∈Ij∑hi
那么:
O
b
j
(
t
)
=
∑
j
=
1
T
[
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
]
+
λ
T
Obj^{(t)} = \sum_{j=1}^T[G_jw_j+\frac{1}{2}(H_j+\lambda)w_j^2]+ \lambda T
Obj(t)=j=1∑T[Gjwj+21(Hj+λ)wj2]+λT
我们要计算每个点的预测值,只需要令目标值loss的一阶导数为0即可,
w
j
∗
=
−
G
j
H
j
+
λ
w_j^*=-\frac{G_j}{H_j+\lambda}
wj∗=−Hj+λGj
相应的目标极值为:
O b j = − 1 2 ∑ j = 1 T G j 2 H j + λ + λ T Obj = -\frac{1}{2}\sum_{j=1}^{T}\frac{G_j^2}{H_j + \lambda} + \lambda T Obj=−21j=1∑THj+λGj2+λT
进行到这一步,模型推导基本结束了,但是有个问题还没有点明,没讲明白,当前这课树是如何建立起来的?
2.4 如何建立基础模型?
我们知道了目标函数,也知道了该树的目标极值表示方法。那么现在有两种方法可以找到最优模型:一种是将所有的模型找出来,分别计算它的目标函数值,显然这是不肯能的;第二种是利用贪心算法来优化:
a、从深度为0的树开始,对每个叶节点枚举所有的可用特征
b、 针对每个特征,把属于该节点的训练样本根据该特征值升序排列,通过线性扫描的方式来决定该特征的最佳分裂点,并记录该特征的最大收益(采用最佳分裂点时的收益)
c、 选择收益最大的特征作为分裂特征,用该特征的最佳分裂点作为分裂位置,把该节点生长出左右两个新的叶节点,并为每个新节点关联对应的样本集。
d、回到第1步,递归执行到满足特定条件为止。
收益怎么算?如果我们要最小化目标函数,那么收益就是分列前的目标值减去分裂后的目标值,
G
a
i
n
=
1
2
[
G
L
2
H
L
+
λ
+
G
R
2
H
R
+
λ
−
(
G
L
+
G
R
)
2
H
L
+
H
R
+
λ
]
−
γ
Gain =\frac{1}{2}[ \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=21[HL+λGL2+HR+λGR2−HL+HR+λ(GL+GR)2]−γ
G
j
=
∑
i
∈
I
j
g
i
H
j
=
∑
i
∈
I
j
h
i
\begin{aligned} G_j & =\sum_{i\in I_j}g_i\\ H_j & =\sum_{i\in I_j}h_i \end{aligned}
GjHj=i∈Ij∑gi=i∈Ij∑hi
g
i
=
∂
y
^
i
t
−
1
(
y
^
i
t
−
1
−
y
i
)
=
2
(
y
^
i
t
−
1
(
y
^
i
t
−
1
−
y
i
)
h
i
=
∂
y
^
i
t
−
1
2
(
y
^
i
t
−
1
−
y
i
)
2
=
2
\begin{aligned} &g_i=\partial_{\hat{y}_i^{t-1}}(\hat{y}_i^{t-1}-y_i) = 2(\hat{y}_i^{t-1}(\hat{y}_i^{t-1}-y_i)\\ &h_i=\partial_{\hat{y}_i^{t-1}}^2(\hat{y}_i^{t-1}-y_i)^2=2 \end{aligned}
gi=∂y^it−1(y^it−1−yi)=2(y^it−1(y^it−1−yi)hi=∂y^it−12(y^it−1−yi)2=2
3,总结
理解xgb的关键在于理解节点如何分裂的,增益是如何计算的,树与树之间是如何结合在一起的。
关于XGB模型的特点、优势、劣势,与RF、GBDT、LGB的区别于联系,将会在下一篇中详细总结,这些总结是高频面试的问题,同时也是理解和应用XGB的关键。
集成学习1——XGBoost
集成学习2——XGBoost本身的特点,及XGB与GBDT、LGB、RF的区别于联系
参考文献:
https://www.jianshu.com/p/48e82dbb142b
https://zhuanlan.zhihu.com/p/29765582