引言
集成学习中的提升法是一种常见的统计学习方法,通常的思路是改变训练数据的概率分布(即训练数据的权值分布),针对不同训练数据分布调用弱学习方法学习一系列的弱分类器。因此针对Boosting方法,就有两个地方需要注意:
- 每一轮训练如何改变训练数据的权值分布和概率分布
- 如何将弱分类器组合成一个强分类器
以Boosting算法里常见的AdaBoost算法为例,对于第1个问题,AdaBoost的方法是提升被前一轮弱分类器错误分类的样本的权值,降低被正确分类样本的权值;对于第2个问题,AdaBoost采取加权多数表决的方法,加大分类误差率小的弱分类器的权值,减少分类误差率大的弱分类器的权值。
针对这两个问题,大部分Boosting算法都是用**加法模型(additive model)来组合弱分类器,然后用前向分步算法(forward stagewise algorithm)**来训练改变训练数据的权值和概率分布(包括AdaBoost算法)。
前向分步算法
考虑加法模型:
f ( x ) = ∑ m = 1 M β m b ( x ; γ m ) b ( x ; γ m ) 是基函数; γ m 是基函数参数, β m 是基函数的系数 f(x)=\sum_{m=1}^{M} \beta_{m} b\left(x ; \gamma_{m}\right) \\ \text{$b(x;\gamma_{m})$是基函数;$\gamma_m$是基函数参数,$\beta_m$是基函数的系数} f(x)=m=1∑Mβmb(x;γm)b(x;γm)是基函数;γm是基函数参数,βm是基函数的系数
在给定训练数据以及损失函数 L ( y , f ( x ) ) L(y,f(x)) L(y,f(x))的条件下,学习加法模型 f ( x ) f(x) f(x)就是一个经验风险极小化问题即损失函数极小化问题:
min
β
m
,
γ
m
∑
i
=
1
N
L
(
y
i
,
∑
m
=
1
M
β
m
b
(
x
i
;
γ
m
)
)
\min _{\beta_{m}, \gamma_{m}} \sum_{i=1}^{N} L\left(y_{i}, \sum_{m=1}^{M} \beta_{m} b\left(x_{i} ; \gamma_{m}\right)\right)
βm,γmmini=1∑NL(yi,m=1∑Mβmb(xi;γm))
直接求解这个的最小值是个很复杂的优化问题,因此我们采用前向分步算法来解决这一优化问题。
前向分布算法的思路是:因为学习的是加法模型,若能从前到后,每一步只学习一个基函数及其系数,逐步逼近优化目标函数,那么就可以简化复杂度。每步只需要优化如下损失函数
min β , γ ∑ i = 1 N L ( y i , β b ( x i ; γ ) ) \min _{\beta, \gamma} \sum_{i=1}^{N} L\left(y_{i}, \beta b\left(x_{i} ; \gamma\right)\right) β,γmini=1∑NL(yi,βb(xi;γ))
这样的话,原本需要同时求解从 m = 1 m=1 m=1到 M M M所有参数 β m , γ m \beta_m, \gamma_m βm,γm的优化问题就简化为逐次求解 β m , γ m \beta_m, \gamma_m βm,γm的优化问题。
负梯度拟合
GBDT也是Boosting算法的一种,但却和Adaboost有很大的不同。
Adaboosting的主要思想是:根据前一轮模型的预测结果,提过对预测结果错误的样本的关注,即改变下一轮训练数据的样本分布,再次进行训练。最后将这些模型结合起来,形成最终的模型。
GBDT的思想:基于前一轮迭代得到的强学习器 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))),在不该变前一个模型的基础上,对上一轮模型的残差进行拟合。即这一轮的拟合样本集就办成了 ( x 1 , y 1 − f t − 1 ( x 1 ) ) , ( x 2 , y 2 − f t − 1 ( x 2 ) ) , … ( x n , y n − f t − 1 ( x n ) ) \left(x_{1}, y_{1}-f_{t-1}\left(x_{1}\right)\right),\left(x_{2}, y_{2}-f_{t-1}\left(x_{2}\right)\right), \ldots\left(x_{n}, y_{n}-f_{t-1}\left(x_{n}\right)\right) (x1,y1−ft−1(x1)),(x2,y2−ft−1(x2)),…(xn,yn−ft−1(xn))( y i − f t − 1 ( x ) y_i - f_{t-1}(x) yi−ft−1(x)被称为残差,即上一轮模型没有拟合好的部分)。
对于回归问题,一般的损失是平方损失函数: L ( y , F ( x ) ) = 1 2 ( y − F ( X ) ) 2 L(y, F(x))=\frac{1}{2}(y-F(X))^{2} L(y,F(x))=21(y−F(X))2,具体形式就是: 1 2 ∑ 0 n ( y i − F ( x i ) ) 2 \frac{1}{2} \sum_{0}^{n}\left(y_{i}-F\left(x_{i}\right)\right)^{2} 21∑0n(yi−F(xi))2,这就是我们想最小化的东西。
损失函数的一阶导数是:
∂
J
∂
F
(
x
i
)
=
∂
∑
i
L
(
y
i
,
F
(
x
i
)
)
∂
F
(
x
i
)
=
∂
L
(
y
i
,
F
(
x
i
)
)
∂
F
(
x
i
)
=
F
(
x
i
)
−
y
i
\frac{\partial J}{\partial F\left(x_{i}\right)}=\frac{\partial \sum_{i} L\left(y_{i}, F\left(x_{i}\right)\right)}{\partial F\left(x_{i}\right)}=\frac{\partial L\left(y_{i}, F\left(x_{i}\right)\right)}{\partial F\left(x_{i}\right)}=F\left(x_{i}\right)-y_{i}
∂F(xi)∂J=∂F(xi)∂∑iL(yi,F(xi))=∂F(xi)∂L(yi,F(xi))=F(xi)−yi
正好残差就是负梯度:
y
i
−
F
(
x
i
)
=
−
∂
J
∂
F
(
x
i
)
y_{i}-F\left(x_{i}\right)=-\frac{\partial J}{\partial F\left(x_{i}\right)}
yi−F(xi)=−∂F(xi)∂J
也就是说,我们对残差的拟合就是对损失函数负梯度的拟合
目标函数
对于普通的机器学习模型而言,其目标函数可以定义为如下:
O
b
j
=
∑
i
=
1
n
l
(
y
i
,
y
^
i
)
+
∑
k
=
1
K
Ω
(
f
k
)
O b j=\sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}\right)+\sum_{k=1}^{K} \Omega\left(f_{k}\right)
Obj=i=1∑nl(yi,y^i)+k=1∑KΩ(fk)
前面是
l
o
s
s
loss
loss函数,后面
Ω
\Omega
Ω是正则化项。
结合前向分步算法的原理,在第
t
t
t步的目标函数是:
O b j ( t ) = ∑ i = 1 n l ( y i , y ^ i t ) + ∑ i = 1 t Ω ( h i ) = ∑ i = 1 n l ( y i , y ^ i t − 1 + h t ( x i ) ) + Ω ( h t ) + constant \begin{array}{c}{O b j^{(t)}=\sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}^{t}\right)+\sum_{i=1}^{t} \Omega\left(h_{i}\right)} \\ {=\sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}^{t-1}+h_{t}\left(x_{i}\right)\right)+\Omega\left(h_{t}\right)+\text {constant }}\end{array} Obj(t)=∑i=1nl(yi,y^it)+∑i=1tΩ(hi)=∑i=1nl(yi,y^it−1+ht(xi))+Ω(ht)+constant
最优化该目标函数就是求的 h t ( x ) h_t(x) ht(x)
由泰勒公式的一阶展开式:
f
(
x
+
Δ
x
)
≈
f
(
x
)
+
f
′
(
x
)
Δ
x
f(x+\Delta x) \approx f(x)+f^{\prime}(x) \Delta x
f(x+Δx)≈f(x)+f′(x)Δx
对
l
(
y
i
,
y
^
i
t
−
1
+
h
t
(
x
i
)
)
l\left(y_{i}, \hat{y}_{i}^{t-1}+h_{t}\left(x_{i}\right)\right)
l(yi,y^it−1+ht(xi)) 做一阶泰勒展开得到:
l ( y i , y ^ i t − 1 + h t ( x i ) ) = l ( y i , y ^ i t − 1 ) + g i h t ( x i ) l\left(y_{i}, \hat{y}_{i}^{t-1}+h_{t}\left(x_{i}\right)\right)=l\left(y_{i}, \hat{y}_{i}^{t-1}\right)+g_{i} h_{t}\left(x_{i}\right) l(yi,y^it−1+ht(xi))=l(yi,y^it−1)+giht(xi)
g i 是 l ( y i , y ^ i t − 1 ) 关于 y ^ t − 1 的一阶导 \text{$g_i$是$l(y_i, \hat y_i^{t-1})$关于$\hat y^{t-1}$的一阶导} gi是l(yi,y^it−1)关于y^t−1的一阶导
此时,目标函数(不考虑正则化项)则变成:
O b j ( t ) = ∑ i = 1 n [ l ( y i , y ^ i t − 1 ) + g i h t ( x i ) ] O b j ( t − 1 ) = ∑ i = 1 n [ l ( y i , y ^ i t − 1 ) ] \begin{array}{c}{O b j^{(t)}=\sum_{i=1}^{n}\left[l\left(y_{i}, \hat{y}_{i}^{t-1}\right)+g_{i} h_{t}\left(x_{i}\right)\right]} \\ {O b j^{(t-1)}=\sum_{i=1}^{n}\left[l\left(y_{i}, \hat{y}_{i}^{t-1}\right)\right]}\end{array} Obj(t)=∑i=1n[l(yi,y^it−1)+giht(xi)]Obj(t−1)=∑i=1n[l(yi,y^it−1)]
我们肯定希望 O b j Obj Obj 函数每步都减小,即 O b j ( t ) < O b j ( t − 1 ) O b j^{(t)}<O b j^{(t-1)} Obj(t)<Obj(t−1),关键就在于 ∑ i = 1 n g i h t ( x i ) \sum_{i=1}^{n}g_{i} h_{t}(x_{i}) ∑i=1ngiht(xi),我们不知道 g i g_i gi 是正是负,那么只需让 h t ( x i ) = − α g i h_{t}\left(x_{i}\right)=-\alpha g_{i} ht(xi)=−αgi( α \alpha α是我们任取的正常数)就能让 ∑ i = 1 n g i h t ( x i ) \sum_{i=1}^{n}g_{i} h_{t}(x_{i}) ∑i=1ngiht(xi) 恒为负了。而 − g i -g_{i} −gi正是负梯度!!!
分类
上面一直在用回归的例子做推导,GBDT的分类算法从思想上和GBDT的回归算法没有区别,但是由于样本输出不是连续的值,而是离散的类别,导致我们无法直接从输出类别去拟合类别输出的误差。
为了解决这个问题,主要有两个方法,一个是用指数损失函数,此时GBDT退化为Adaboost算法。另一种方法是用类似于逻辑回归的对数似然损失函数的方法。也就是说,我们用的是类别的预测概率值和真实概率值的差来拟合损失。本文仅讨论用对数似然损失函数的GBDT分类。而对于对数似然损失函数,我们又有二元分类和多元分类的区别。
二分类
对于二元GBDT,如果用类似于逻辑回归的对数似然损失函数,则损失函数为:
L ( y , f ( x ) ) = log ( 1 + exp ( − y f ( x ) ) ) L(y, f(x))=\log (1+\exp (-y f(x))) L(y,f(x))=log(1+exp(−yf(x)))
其中
y
∈
{
−
1
,
+
1
}
y \in\{-1,+1\}
y∈{−1,+1},则此时的负梯度为:
r
t
i
=
−
[
∂
L
(
y
,
f
(
x
i
)
)
∂
f
(
x
i
)
]
f
(
x
)
=
f
t
−
1
(
x
)
=
y
i
/
(
1
+
exp
(
y
i
f
(
x
i
)
)
)
r_{t i}=-\left[\frac{\partial L\left(y, f\left(x_{i}\right)\right) }{\partial f\left(x_{i}\right)}\right]_{f(x)=f_{t-1}(x)}=y_{i} /\left(1+\exp \left(y_{i} f\left(x_{i}\right)\right)\right)
rti=−[∂f(xi)∂L(y,f(xi))]f(x)=ft−1(x)=yi/(1+exp(yif(xi)))
对于生成的决策树,我们各个叶子节点的最佳负梯度拟合值为:
c t j = arg min ⎵ c ∑ x i ∈ R t j log ( 1 + exp ( − y i ( f t − 1 ( x i ) + c ) ) ) c_{t j}=\underbrace{\arg \min }_{c} \sum_{x_{i} \in R_{t j}} \log \left(1+\exp \left(-y_{i}\left(f_{t-1}\left(x_{i}\right)+c\right)\right)\right) ctj=c argminxi∈Rtj∑log(1+exp(−yi(ft−1(xi)+c)))
由于上式比较难优化,我们一般使用近似值代替:
c t j = ∑ x i ∈ R t j r t i / ∑ x i ∈ R t j ∣ r t i ∣ ( 1 − ∣ r t i ∣ ) c_{t j}=\sum_{x_{i} \in R_{t j}} r_{t i} / \sum_{x_{i} \in R_{t j}}\left|r_{t i}\right|\left(1-\left|r_{t i}\right|\right) ctj=xi∈Rtj∑rti/xi∈Rtj∑∣rti∣(1−∣rti∣)
除了负梯度计算和叶子节点的最佳负梯度拟合的线性搜索,二元GBDT分类和GBDT回归算法过程相同。
多分类
假设类别数为K,则此时我们的对数似然损失函数为:
L
(
y
,
f
(
x
)
)
=
−
∑
k
=
1
K
y
k
log
p
k
(
x
)
p
k
(
x
)
=
exp
(
f
k
(
x
)
)
/
∑
l
=
1
K
exp
(
f
l
(
x
)
)
若样本输出类别为k,则
y
k
=
1
L(y, f(x))=-\sum_{k=1}^{K} y_{k} \log p_{k}(x) \\ p_{k}(x)=\exp \left(f_{k}(x)\right) / \sum_{l=1}^{K} \exp \left(f_{l}(x)\right)\\ \text{若样本输出类别为k,则$y_{k}=1$}
L(y,f(x))=−k=1∑Kyklogpk(x)pk(x)=exp(fk(x))/l=1∑Kexp(fl(x))若样本输出类别为k,则yk=1
由以上两式,我们可以计算第
t
t
t轮的第
i
i
i个样本对应的类别
l
l
l的负梯度为:
r
t
i
l
=
−
[
∂
L
(
y
i
,
f
(
x
i
)
)
)
∂
f
(
x
i
)
]
f
k
(
x
)
=
f
l
,
t
−
1
(
x
)
=
y
i
l
−
p
l
,
t
−
1
(
x
i
)
r_{t i l}=-\left[\frac{\partial L\left(y_{i}, f\left(x_{i}\right)\right) )}{\partial f\left(x_{i}\right)}\right]_{f_{k}(x)=f_{l, t-1}(x)}=y_{i l}-p_{l, t-1}\left(x_{i}\right)
rtil=−[∂f(xi)∂L(yi,f(xi)))]fk(x)=fl,t−1(x)=yil−pl,t−1(xi)
其实这里的误差就是样本 i i i 对应类别的真实概率和 t − 1 t-1 t−1轮预测概率的差值。
对于生成的决策树,我们各个叶子节点的最佳负梯度拟合值为:
c
t
j
l
=
arg
min
⎵
c
j
l
∑
i
=
0
m
∑
k
=
1
K
L
(
y
k
,
f
t
−
1
,
l
(
x
)
+
∑
j
=
0
J
c
j
l
I
(
x
i
∈
R
t
j
)
)
c_{t j l}=\underbrace{\arg \min }_{c_{j l}} \sum_{i=0}^{m} \sum_{k=1}^{K} L\left(y_{k}, f_{t-1, l}(x)+\sum_{j=0}^{J} c_{j l} I\left(x_{i} \in R_{t j}\right)\right)
ctjl=cjl
argmini=0∑mk=1∑KL(yk,ft−1,l(x)+j=0∑JcjlI(xi∈Rtj))
由于上式比较难优化,我们一般使用近似值代替:
c t j l = K − 1 K ∑ x i ∈ R t i l r t i l ∑ x i ∈ R i t ∣ r t i l ∣ ( 1 − ∣ r t i l ∣ ) c_{t j l}=\frac{K-1}{K} \frac{\sum_{x_{i} \in R_{t i l}} r_{t i l}}{\sum_{x_{i} \in R_{i t}}\left|r_{t i l}\right|\left(1-\left|r_{t i l}\right|\right)} ctjl=KK−1∑xi∈Rit∣rtil∣(1−∣rtil∣)∑xi∈Rtilrtil
损失函数
分类算法
分类算法的损失函数一般有对数损失函数和指数损失函数两种:
- 如果是指数损失函数,则损失函数表达式为: L ( y , f ( x ) ) = exp ( − y f ( x ) ) L(y, f(x))=\exp (-y f(x)) L(y,f(x))=exp(−yf(x))
- 如果是对数损失函数,分为二元分类和多元分类两种,见上面。
回归算法
回归算法,常用损失函数有如下4种:
- 均方差,其表达式为: L ( y , f ( x ) ) = ( y − f ( x ) ) 2 L(y, f(x))=(y-f(x))^{2} L(y,f(x))=(y−f(x))2
- 平均绝对误差,其表达式为:
L
(
y
,
f
(
x
)
)
=
∣
y
−
f
(
x
)
∣
L(y, f(x))=|y-f(x)|
L(y,f(x))=∣y−f(x)∣
- 对应负梯度误差为: sign ( y i − f ( x i ) ) \operatorname{sign}\left(y_{i}-f\left(x_{i}\right)\right) sign(yi−f(xi))
- Huber损失,它是均方差和绝对损失的折衷产物,对于远离中心的异常点,采用绝对损失,而中心附近的点采用均方差。这个界限一般用分位数点度量,其表达式为:
L
(
y
,
f
(
x
)
)
=
{
1
2
(
y
−
f
(
x
)
)
2
∣
y
−
f
(
x
)
∣
≤
δ
δ
(
∣
y
−
f
(
x
)
∣
−
δ
2
)
∣
y
−
f
(
x
)
∣
>
δ
L(y, f(x))=\left\{\begin{array}{ll}{\frac{1}{2}(y-f(x))^{2}} & {|y-f(x)| \leq \delta} \\ {\delta\left(|y-f(x)|-\frac{\delta}{2}\right)} & {|y-f(x)|>\delta}\end{array}\right.
L(y,f(x))={21(y−f(x))2δ(∣y−f(x)∣−2δ)∣y−f(x)∣≤δ∣y−f(x)∣>δ
- 负梯度误差为: r ( y i , f ( x i ) ) = { y i − f ( x i ) ∣ y i − f ( x i ) ∣ ≤ δ δ sign ( y i − f ( x i ) ) ∣ y i − f ( x i ) ∣ > δ r\left(y_{i}, f\left(x_{i}\right)\right)=\left\{\begin{array}{ll}{y_{i}-f\left(x_{i}\right)} & {\left|y_{i}-f\left(x_{i}\right)\right| \leq \delta} \\ {\delta \operatorname{sign}\left(y_{i}-f\left(x_{i}\right)\right)} & {\left|y_{i}-f\left(x_{i}\right)\right|>\delta}\end{array}\right. r(yi,f(xi))={yi−f(xi)δsign(yi−f(xi))∣yi−f(xi)∣≤δ∣yi−f(xi)∣>δ
- 分位数损失,它对应的是分位数回归的损失函数,其表达式为:
L
(
y
,
f
(
x
)
)
=
∑
y
≥
f
(
x
)
θ
∣
y
−
f
(
x
)
∣
+
∑
y
<
f
(
x
)
(
1
−
θ
)
∣
y
−
f
(
x
)
∣
L(y, f(x))=\sum_{y \geq f(x)} \theta|y-f(x)|+\sum_{y<f(x)}(1-\theta)|y-f(x)|
L(y,f(x))=∑y≥f(x)θ∣y−f(x)∣+∑y<f(x)(1−θ)∣y−f(x)∣,其中
θ
\theta
θ为分位数,需要我们在回归前指定。
- 负梯度误差为: r ( y i , f ( x i ) ) = { θ y i ≥ f ( x i ) θ − 1 y i < f ( x i ) r\left(y_{i}, f\left(x_{i}\right)\right)=\left\{\begin{array}{ll}{\theta} & {y_{i} \geq f\left(x_{i}\right)} \\ {\theta-1} & {y_{i}<f\left(x_{i}\right)}\end{array}\right. r(yi,f(xi))={θθ−1yi≥f(xi)yi<f(xi)
对于Huber损失和分位数损失,主要用于健壮回归,也就是减少异常点对损失函数的影响。
正则化
GBDT的正则化主要有三种方式:
- 第一种是和Adaboost类似的正则化项,即步长(learning rate)。定义 ν \nu ν,对于前面的弱学习器的迭代: f k ( x ) = f k − 1 ( x ) + h k ( x ) f_{k}(x)=f_{k-1}(x)+h_{k}(x) fk(x)=fk−1(x)+hk(x),如果我们加上了正则化项,则有: f k ( x ) = f k − 1 ( x ) + ν h k ( x ) f_{k}(x)=f_{k-1}(x)+\nu h_{k}(x) fk(x)=fk−1(x)+νhk(x)( 0 < ν ≤ 1 0<\nu \leq 1 0<ν≤1),对于同样的训练集学习效果,较小的 ν \nu ν意味着我们需要更多的弱学习器的迭代次数。通常我们用步长和迭代最大次数一起来决定算法的拟合效果。
- 第二种正则化的方式是通过子采样比例(subsample)。取值为(0,1]。注意这里的子采样和随机森林不一样,随机森林使用的是放回抽样,而这里是不放回抽样。如果取值为1,则全部样本都使用,等于没有使用子采样。如果取值小于1,则只有一部分样本会去做GBDT的决策树拟合。选择小于1的比例可以减少方差,即防止过拟合,但是会增加样本拟合的偏差,因此取值不能太低。推荐在[0.5, 0.8]之间。使用了子采样的GBDT有时也称作随机梯度提升树(Stochastic Gradient Boosting Tree, SGBT)。由于使用了子采样,程序可以通过采样分发到不同的任务去做boosting的迭代过程,最后形成新树,从而减少弱学习器难以并行学习的弱点。
- 第三种是对于弱学习器即CART回归树进行正则化剪枝。
优缺点
GBDT主要的优点有:
- 可以灵活处理各种类型的数据,包括连续值和离散值。
- 在相对少的调参时间情况下,预测的准确率也可以比较高。这个是相对SVM来说的。
- 使用一些健壮的损失函数,对异常值的鲁棒性非常强。比如 Huber损失函数和Quantile损失函数。
GBDT的主要缺点有:
- 由于弱学习器之间存在依赖关系,难以并行训练数据。不过可以通过自采样的SGBT来达到部分并行。