1. 概述
首先GBDT是集成学习的一种,而且属于boosting家族。我们知道Bagging的思想比较简单,即每一次从原始数据中根据均匀概率分布有放回的抽取和原始数据大小相同的样本集合,样本点可能出现重复,然后对每一次产生的训练集构造一个分类器,再对分类器进行组合。常见的随机森林算法就是bagging的集成算法。
boosting的每一次抽样的样本分布都是不一样的。每一次迭代,都根据上一次迭代的结果,增加被错误分类的样本的权重,使得模型能在之后的迭代中更加注意到难以分类的样本,这是一个不断学习的过程,也是一个不断提升的过程,这也就是boosting思想的本质所在。迭代之后,将每次迭代的基分类器进行集成。那么如何进行样本权重的调整和分类器的集成是我们需要考虑的关键问题。传统的Adaboost,利用前一轮迭代弱学习器的误差率来更新训练集的权重,这样一轮轮的迭代下去。GBDT同样也是一种迭代的方法,使用了前向分布算法,但是弱学习器限定了只能使用CART回归树模型,同时迭代思路和Adaboost也有所不同。
2. 提升树算法
接触过GBDT的想必都听说过残差这个概念,那么什么是残差呢?
假设有一组数据,
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
…
(
x
n
,
y
n
)
\left(x_1, y_1\right),\left(x_2, y_2\right), \ldots\left(x_n, y_n\right)
(x1,y1),(x2,y2),…(xn,yn) ,有一个模型
F
(
x
)
F(x)
F(x) ,用这个模型去拟合 这一批数据,拟合的过程中使得我们选择的损失函数最小,最终成功拟合后,假设得到
F
(
x
1
)
=
1.2
,
F
(
x
2
)
=
2.5
F\left(x_1\right)=1.2 , F\left(x_2\right)=2.5
F(x1)=1.2,F(x2)=2.5 ,但实际的
y
1
=
1.1
,
y
2
=
2.4
y_1=1.1 , y_2=2.4
y1=1.1,y2=2.4 ,可以看出虽然已经拟合的 不错了,但和真实的还是有一点差距,如果想要进一步提升拟合的效果,一个最直观的做法就是使 用一个新的学习器对上一批数据拟合过后的残差进一步拟合,也就是形成了一批新的数据
(
x
1
,
y
1
−
F
(
x
1
)
)
,
(
x
2
,
y
2
−
F
(
x
2
)
)
,
…
(
x
n
,
y
n
−
F
(
x
n
)
)
\left(x_1, y_1-F\left(x_1\right)\right),\left(x_2, y_2-F\left(x_2\right)\right), \ldots\left(x_n, y_n-F\left(x_n\right)\right)
(x1,y1−F(x1)),(x2,y2−F(x2)),…(xn,yn−F(xn)) 。所以残差实际上真实值和预 测值之差也就是
y
−
F
(
x
)
y-F(x)
y−F(x) 。
介绍完了残差,再来介绍一下加法模型。提升树模型可以表示为以决策树为基本学习器的加法模 型,公式如下:
f
(
x
)
=
f
M
(
x
)
=
∑
m
=
1
M
h
m
(
x
;
a
m
)
f(\mathbf{x})=f_M(\mathbf{x})=\sum_{m=1}^M h_m\left(\mathbf{x} ; a_m\right)
f(x)=fM(x)=m=1∑Mhm(x;am)
- 其中 h m ( x ; a m ) h_m\left(x ; a_m\right) hm(x;am) 表示的是第 m \mathrm{m} m 颗决策树
- M M M 表示基学习器决策树的数量
-
a
m
a_m
am 表示决策树的参数
而这样的加法模型怎么去求解它呢,就是用的最直观的迭代求解,也称之为前向分步算法。首先 确定初始提升树: f 0 ( x ) = 0 f_0(x)=0 f0(x)=0
然后第m步的模型为: f m ( x ) = f m − 1 ( x ) + h ( x ; a m ) f_m(x)=f_{m-1}(x)+h\left(x ; a_m\right) fm(x)=fm−1(x)+h(x;am)
然后通过经验风险极小化 (损失函数) 来确定 a ^ m = argmin a n ∑ i = 1 N L ( y i , f m ( x i ) \hat{a}_m=\operatorname{argmin}_{a_n} \sum_{i=1}^N L\left(y_i, f_m\left(x_i\right)\right. a^m=argminan∑i=1NL(yi,fm(xi) ),其中 L ( ⋅ ) L(\cdot) L(⋅) 为对应选择的损失函数。
到这里看起来仍然非常简单,只是把我们之前优化一个模型,进行分步完成进而集成了而已。
这里我们假设现在面对的是一个回归问题,选择的损失函数是平方损失,则此时有:
loss = ∑ i = 1 N L ( y i , f m ( x i ) ) = ∑ i = 1 N ( y i − f m − 1 ( x i ) − h m ( x i ; a m ) ) 2 \text { loss }=\sum_{i=1}^N L\left(y_i, f_m\left(x_i\right)\right)=\sum_{i=1}^N\left(y_i-f_{m-1}\left(x_i\right)-h_m\left(x_i ; a_m\right)\right)^2 loss =i=1∑NL(yi,fm(xi))=i=1∑N(yi−fm−1(xi)−hm(xi;am))2
此时可以看出来, y i − f m − 1 ( x i ) y_i-f_{m-1}\left(x_i\right) yi−fm−1(xi) 实质上就是上面说的残差,也可以看出来基于加法模型的提升 树算法当前的分类器实质上是在拟合上一个分类器之后数据的残差。
在这里我们选择的是回归问题的平方差损失函数,看起来一切都是那么自然,但并不是所有的损失 函数都有这样的性质,所以想要找到的方法的关键是如何对所有的任务的损失函数都有效。
3. 梯度提升树
梯度提升树,顾名思义,是利用损失函数的负梯度在当前模型的值作为残差的一个近似值,进行拟 合回归树,这样只要可以求梯度的函数,我们都可以进行求解。
那么,为什么可以使用梯度近似替代残差呢? 我们讲刚刚的损失函数写出来,同时为了简便,去 掉求和符合和下标,改用向量化表示,则损失函数为:
loss
=
L
(
y
,
f
m
(
x
)
)
=
L
(
y
,
f
m
−
1
(
x
)
+
h
m
(
x
;
a
m
)
)
\text { loss }=L\left(y, f_m(x)\right)=L\left(y, f_{m-1}(x)+h_m\left(x ; a_m\right)\right)
loss =L(y,fm(x))=L(y,fm−1(x)+hm(x;am))
按照泰勒一阶展开式(注意,在这里xgboost用的是二阶展开式)进行展开:
loss
=
L
(
y
,
f
m
−
1
(
x
)
+
h
m
(
x
;
a
m
)
)
=
L
(
y
,
f
m
−
1
(
x
)
)
+
∂
L
(
y
,
f
m
−
1
(
x
)
)
∂
f
m
−
1
(
x
)
h
m
(
x
;
a
m
)
\text { loss }=L\left(y, f_{m-1}(x)+h_m\left(x ; a_m\right)\right)=L\left(y, f_{m-1}(x)\right)+\frac{\partial L\left(y, f_{m-1}(x)\right)}{\partial f_{m-1}(x)} h_m\left(x ; a_m\right)
loss =L(y,fm−1(x)+hm(x;am))=L(y,fm−1(x))+∂fm−1(x)∂L(y,fm−1(x))hm(x;am)
在此处,我们发现
L
(
y
,
f
m
−
1
(
x
)
)
L\left(y, f_{m-1}(x)\right)
L(y,fm−1(x)) 是上一步m-1对应的损失,如果在此处,我们令:
h
m
(
x
;
a
m
)
=
−
∂
L
(
y
,
f
m
−
1
(
x
)
)
∂
f
n
≤
−
1
′
(
x
)
h_m\left(x ; a_m\right)=-\frac{\partial L\left(y, f_{m-1}(x)\right)}{\partial f_{n \leq-1}^{\prime}(x)}
hm(x;am)=−∂fn≤−1′(x)∂L(y,fm−1(x))
则可以保证,上式后面的部分减去的一定是一个正数,所以这样取负梯度,可以使得损失一步一步 的降低,故而理论上这种方法是有效的。
理解了这一步,我们将Freidman提出的梯度提升算法写出来,其算法流程如下:
F
0
(
x
)
=
arg
min
ρ
∑
i
=
1
N
L
(
y
i
,
ρ
)
For
m
=
1
to
M
do:
y
~
i
=
−
[
∂
L
(
y
i
,
F
(
x
i
)
)
∂
F
(
x
i
)
]
F
(
x
)
=
F
m
−
1
(
x
)
,
i
=
1
,
N
a
m
=
arg
min
a
,
β
∑
i
=
1
N
[
y
~
i
−
β
h
(
x
i
;
a
)
]
2
ρ
m
=
arg
min
ρ
∑
i
=
1
N
L
(
y
i
,
F
m
−
1
(
x
i
)
+
ρ
h
(
x
i
;
a
m
)
)
F
m
(
x
)
=
F
m
−
1
(
x
)
+
ρ
m
h
(
x
;
a
m
)
e
n
d
F
o
r
\begin{aligned} &F_0(\mathbf{x})=\arg \min _\rho \sum_{i=1}^N L\left(y_i, \rho\right) \\ &\text { For } m=1 \text { to } M \text { do: } \\ &\qquad \quad \tilde{y}_i=-\left[\frac{\partial L\left(y_i, F\left(\mathbf{x}_i\right)\right)}{\partial F\left(\mathbf{x}_i\right)}\right]_{F(\mathbf{x})=F_{m-1}(\mathbf{x})}, i=1, N \\ &\qquad \quad \mathbf{a}_m=\arg \min _{\mathbf{a}, \beta} \sum_{i=1}^N\left[\tilde{y}_i-\beta h\left(\mathbf{x}_i ; \mathbf{a}\right)\right]^2 \\ &\qquad \quad \rho_m=\arg \min _\rho \sum_{i=1}^N L\left(y_i, F_{m-1}\left(\mathbf{x}_i\right)+\rho h\left(\mathbf{x}_i ; \mathbf{a}_m\right)\right) \\ &\qquad \quad F_m(\mathbf{x})=F_{m-1}(\mathbf{x})+\rho_m h\left(\mathbf{x} ; \mathbf{a}_m\right)\\ &end \quad For \end{aligned}
F0(x)=argρmini=1∑NL(yi,ρ) For m=1 to M do: y~i=−[∂F(xi)∂L(yi,F(xi))]F(x)=Fm−1(x),i=1,Nam=arga,βmini=1∑N[y~i−βh(xi;a)]2ρm=argρmini=1∑NL(yi,Fm−1(xi)+ρh(xi;am))Fm(x)=Fm−1(x)+ρmh(x;am)endFor
算法中, N表示数据的数量,M表示基分类器的数量,
h
(
x
i
;
a
m
)
h\left(x_i ; a_m\right)
h(xi;am) 表示基本分类器 ,
a
m
a_m
am 表示拟合负梯度能力最好的分类器参数,负梯度只是表示下降的方向,但是下降多少没有确定,
ρ
m
\rho_m
ρm 可以认为是下降最快的步长(也可以认为是学习率), 可以让Loss最小,可以用线性搜系的方式来估计
ρ
m
\rho_m
ρm 的值。
我们的基分类器是回归树,一个包含J个叶子节点的回归树模型可以表示为:
h
(
x
;
{
b
j
,
R
j
}
1
J
)
=
∑
b
=
j
J
b
j
I
(
x
∈
R
j
)
h\left(x ;\left\{b_j, R_j\right\}_1^J\right)=\sum_{b=j}^J b_j I\left(x \in R_j\right)
h(x;{bj,Rj}1J)=b=j∑JbjI(x∈Rj)
其中
{
R
j
}
1
J
\left\{R_j\right\}_1^J
{Rj}1J 不相交的区域,可以认为落在一颗决策树叶子节点上的x的值的集合,它们的集合覆盖了预测值的空间,
{
b
j
}
1
J
\left\{b_j\right\}_1^J
{bj}1J 是叶子节点的值,也就是决策树预测的值,可以认为是模型
h
h
h 的系数
利用上述回归树的表示方式,可以将上述算法第6步等价替换为:
F
m
(
x
)
=
F
m
−
1
(
x
)
+
ρ
m
∑
j
=
1
J
b
j
m
I
(
x
∈
R
j
m
)
F_m(x)=F_{m-1}(x)+\rho_m \sum_{j=1}^J b_{j m} I\left(x \in R_{j m}\right)
Fm(x)=Fm−1(x)+ρmj=1∑JbjmI(x∈Rjm)
而
b
j
m
b_{j m}
bjm 常用的计算方式可以取落在该叶子节点的样本点的平均值,也就是:
b
j
m
=
average
x
i
∈
R
j
m
y
~
i
b_{j m}=\text { average }_{x_i \in R_{j m}} \tilde{y}_i
bjm= average xi∈Rjmy~i
有了下降的方向,我们还需要最好的步长,缩放因子
ρ
m
\rho_m
ρm 是流程5中线性搜索方式的一种解决方 案,从上面可以看出,我们是先求的
b
j
m
b_{j m}
bjm ,然后在求解
ρ
m
\rho_m
ρm ,我们能否同时求解呢? 另
γ
j
m
=
ρ
m
b
j
m
\gamma_{j m}=\rho_m b_{j m}
γjm=ρmbjm ,则公式a可以被表示为:
F
m
(
x
)
=
F
m
−
1
(
x
)
+
∑
j
=
1
J
γ
j
m
I
(
x
∈
R
j
m
)
F_m(x)=F_{m-1}(x)+\sum_{j=1}^J \gamma_{j m} I\left(x \in R_{j m}\right)
Fm(x)=Fm−1(x)+j=1∑JγjmI(x∈Rjm)
这样就把几个参数合成一个进行求解了,可以通过优化如下公式来获取最优的系
γ
j
m
\gamma_{j m}
γjm :
{
γ
j
m
}
1
J
=
argmin
γ
j
1
J
∑
i
=
1
N
L
(
y
i
,
F
m
−
1
(
x
i
)
+
∑
j
=
1
J
γ
j
I
(
x
∈
R
j
m
)
)
\left\{\gamma_{j m}\right\}_1^J=\operatorname{argmin}_{\gamma_j{ }_1^J} \sum_{i=1}^N L\left(y_i, F_{m-1}\left(x_i\right)+\sum_{j=1}^J \gamma_j I\left(x \in R_{j m}\right)\right)
{γjm}1J=argminγj1Ji=1∑NL(yi,Fm−1(xi)+j=1∑JγjI(x∈Rjm))
由于回归树产生的叶子节点各个区域之间是不相交的,且所有的样本最终都会属于某个叶子节点, 所以公式c可以表示为:
γ
j
m
=
argmin
γ
∑
x
i
∈
R
j
m
L
(
y
i
,
F
m
−
1
(
x
i
)
+
γ
)
\gamma_{j m}=\operatorname{argmin}_\gamma \sum_{x_i \in R_{j m}} L\left(y_i, F_{m-1}\left(x_i\right)+\gamma\right)
γjm=argminγ∑xi∈RjmL(yi,Fm−1(xi)+γ)
给定当前
F
m
−
1
(
x
i
)
,
γ
j
m
F_{m-1}\left(x_i\right) , \gamma_{j m}
Fm−1(xi),γjm 可以作为叶子节点的值,该值可以看做是基于损失函数L的每个叶子 节点的最理想的常数更新值,也可以认为
γ
j
m
\gamma_{j m}
γjm 是即有下降方向又有下降步长的值。
所以最终的梯度提升树算法为:
F
0
(
x
)
=
argmin
ρ
∑
i
=
1
N
L
(
y
i
,
ρ
)
For
m
=
1
to
M
do:
y
~
i
=
−
[
∂
L
(
y
,
F
(
x
i
)
)
∂
F
(
x
i
)
]
F
(
x
)
=
F
m
−
1
(
x
)
,
i
=
1
,
N
{
R
j
m
}
1
J
=
J
−
terminal node tree
(
{
y
~
i
,
x
i
}
i
N
)
γ
j
m
=
argmin
γ
∑
x
i
∈
R
j
m
L
(
y
i
,
F
m
−
1
(
x
i
)
+
γ
)
F
m
(
x
)
=
F
m
−
1
(
x
)
+
∑
j
=
1
J
γ
j
m
I
(
x
∈
R
j
m
)
e
n
d
F
o
r
\begin{aligned} F_0(x)&=\operatorname{argmin}_\rho \sum_{i=1}^N L\left(y_i, \rho\right) \\ \text { For } m&=1 \text { to } M \text { do: } \\ \qquad \tilde{y}_i&=-\left[\frac{\partial L\left(y, F\left(x_i\right)\right)}{\partial F\left(x_i\right)}\right]_{F(x)=F_{m-1}(x)}, i=1, N \\ \qquad\left\{R_{j m}\right\}_1^J&=J-\text { terminal node tree }\left(\left\{\tilde{y}_i, x_i\right\}_i^N\right) \\ \qquad \gamma_{j m}&=\operatorname{argmin}_\gamma \sum_{x_i \in R_{j m}} L\left(y_i, F_{m-1}\left(x_i\right)+\gamma\right) \\ \qquad F_m(x)&=F_{m-1}(x)+\sum_{j=1}^J \gamma_{j m} I\left(x \in R_{j m}\right)\\ \quad end \quad For \end{aligned}
F0(x) For my~i{Rjm}1JγjmFm(x)endFor=argminρi=1∑NL(yi,ρ)=1 to M do: =−[∂F(xi)∂L(y,F(xi))]F(x)=Fm−1(x),i=1,N=J− terminal node tree ({y~i,xi}iN)=argminγxi∈Rjm∑L(yi,Fm−1(xi)+γ)=Fm−1(x)+j=1∑JγjmI(x∈Rjm)