这是一篇集成树模型知识的梳理。是我大概3、4年前给自己写的,希望可以对各位读者老爷有帮助。
Boosting
Boosting框架就是假发模型和前向分步算法的一类集成学习的方式。最终的模型就是若干基模型的线性加和,基模型的参数利用前向分布算法确定。
加法模型
加法模型就是基模型的线性组合,这里的基模型既可以是一个相对较弱的分类模型也可是一个回归模型。
加法模型的意思是:第
m
m
m步模型是第
m
−
1
m-1
m−1步的模型加上一个基模型得到的:
f
m
(
x
)
=
f
m
−
1
(
x
)
+
β
m
b
m
(
x
;
γ
m
)
(1)
f_m(x) = f_{m-1}(x)+\beta_{m}b_{m}(x;\gamma_{m}) \tag{1}
fm(x)=fm−1(x)+βmbm(x;γm)(1)
其中
f
m
(
x
)
f_m(x)
fm(x)是第
m
m
m步的模型;
f
m
−
1
(
x
)
f_{m-1}(x)
fm−1(x)是第
m
−
1
m-1
m−1步的模型;
β
m
\beta_{m}
βm是基分类器的权重;
b
m
(
x
;
γ
m
)
b_{m}(x;\gamma_{m})
bm(x;γm)是基模型;
γ
m
\gamma_{m}
γm是基模型的参数。
最终的加法模型表示为:
f
(
x
)
=
∑
m
=
1
M
β
m
b
m
(
x
;
γ
m
)
(2)
f(x)=\sum_{m=1}^{M}\beta_{m}b_{m}(x;\gamma_{m}) \tag{2}
f(x)=m=1∑Mβmbm(x;γm)(2)
其中
f
(
x
)
f(x)
f(x)是最终的模型;
损失函数表示为:
J
(
x
)
=
∑
n
=
1
N
L
(
y
i
,
f
(
x
i
)
)
(3)
J(x) =\sum_{n=1}^{N}L(y_{i},f(x_{i})) \tag{3}
J(x)=n=1∑NL(yi,f(xi))(3)
这里的
L
(
⋅
)
L(\cdot)
L(⋅)是损失函数的具体形式 可以是logloss等。
前向分步算法
该算法是可以求解加法模型
f
(
x
)
f(x)
f(x)的方法,他的基本思想是通过迭代的方法逐步逼近
(
1
)
(1)
(1),即每一步的损失函数是:
∑
n
=
1
N
L
(
y
i
,
f
m
(
x
i
)
)
(4)
\sum_{n=1}^{N}L(y_{i},f_m(x_{i})) \tag{4}
n=1∑NL(yi,fm(xi))(4)
前向分步算法的步骤如下:
输入:训练数据集
T
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
,
(
x
N
,
y
N
)
}
T=\{(x_{1},y_{1}),(x_{2},y_{2}),...,(x_{N},y_{N})\}
T={(x1,y1),(x2,y2),...,(xN,yN)};损失函数
L
(
y
,
f
(
x
)
)
L(y,f(x))
L(y,f(x));基模型集
{
b
m
(
x
;
γ
m
)
}
\{b_{m}(x;\gamma_{m})\}
{bm(x;γm)};
输出:假发模型
f
(
x
)
f(x)
f(x);
- 初始化 f 0 ( x ) = 0 f_{0}(x)=0 f0(x)=0
- 对
m
=
1
,
2
,
.
.
.
,
M
m=1,2,...,M
m=1,2,...,M
a)极小化损失函数(假设已经迭代了 m − 1 m-1 m−1轮,现在要确定第m轮的基模型)得到参数 β m , γ m \beta_{m},\gamma_{m} βm,γm
( β m , γ m ) = arg min β , γ ∑ i = 1 N L ( y i , f m − 1 ( x i ) + β m b m ( x i , γ m ) ) (5) (\beta_{m},\gamma_{m}) = \argmin_{\beta,\gamma} \sum_{i=1}^{N}L(y_{i},f_{m-1}(x_{i})+\beta_{m}b_{m}(x_{i},\gamma_{m})) \tag{5} (βm,γm)=β,γargmini=1∑NL(yi,fm−1(xi)+βmbm(xi,γm))(5)
b) 更新
f m ( x ) = f m − 1 ( x ) + β m b m ( x ; γ m ) (6) f_m(x) = f_{m-1}(x)+\beta_{m}b_{m}(x;\gamma_{m}) \tag{6} fm(x)=fm−1(x)+βmbm(x;γm)(6) - 得到加法模型
f ( x ) = ∑ m = 1 M β m b m ( x ; γ m ) (7) f(x)=\sum_{m=1}^{M}\beta_{m}b_{m}(x;\gamma_{m}) \tag{7} f(x)=m=1∑Mβmbm(x;γm)(7)
Adaboost
Adaboosting是boosting的代表算法,其主要思想是:针对训练样本,在每一轮学习过程中,对前一轮分类错误的样本,在下一轮给与较大的权重使得该样本在下一次学习中获得分类器更多的关注。针对多个弱分类器,Adaboost采用加权多数表决的方法,即加大分类误差小的弱分类器的权重,使其在分类表决中起较大的作用。
Adaboost的步骤(二分类为例)
-
给定训练数据: T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x N , y N ) } T=\{(x_{1},y_{1}),(x_{2},y_{2}),...,(x_{N},y_{N})\} T={(x1,y1),(x2,y2),...,(xN,yN)},初始化训练数据的权重分布 D m D_{m} Dm,最初每个样本的的权重是相同的( w = 1 N w=\frac{1}{N} w=N1)
D 1 = ( w 1 , i , w 1 , 2 , . . . , w 1 , N ) , w 1 , i − 1 N , i = 1 , 2 , . . . , N D_{1}=(w_{1,i},w_{1,2},...,w_{1,N}),w_{1,i}-\frac{1}{N}, i=1,2,...,N D1=(w1,i,w1,2,...,w1,N),w1,i−N1,i=1,2,...,N -
对 m = 1 , 2 , . . . = , M m=1,2,...=,M m=1,2,...=,M:
a)使用具有权重分布 D m D_{m} Dm的训练数据学习得到基模型
G m ( x ) : X → { − 1 , 1 } G_{m}(x):X \to \{-1,1\} Gm(x):X→{−1,1}
b)计算 G m ( x ) G_{m}(x) Gm(x)在训练集上的误差(这个误差要带上权重)
e m = P ( G m ( x i ) ≠ y i ) = ∑ i = 1 N w m , i I ( G m ( x i ) ≠ y i ) e_{m}=P(G_{m}(x_{i})\ne y_{i})=\sum_{i=1}^{N}w_{m,i}I(G_{m}(x_{i})\ne y_{i}) em=P(Gm(xi)=yi)=i=1∑Nwm,iI(Gm(xi)=yi)
c)计算弱分类器的 G m ( x ) G_{m}(x) Gm(x)的表决系数:
α m = 1 2 l o g 1 − e m e m \alpha_{m}=\frac{1}{2}log\frac{1-e_{m}}{e_{m}} αm=21logem1−em
这个表决系数影响了该弱分类器 G m ( x ) G_{m}(x) Gm(x)在最终分类其中的表决作用。当分类器的误差率 e m < 1 2 e_{m}<\frac{1}{2} em<21,表决系数大于0,并且随着 e m e_{m} em的减少而增大。所以分类误差越小的弱分类器在最终分类器中起的表决作用越大。d)更新训练数据的权重分布:
D m + 1 = w m + 1 , i , w m + 1 , 2 , . . . , w m + 1 , N ) D_{m+1}=w_{m+1,i},w_{m+1,2},...,w_{m+1,N}) Dm+1=wm+1,i,wm+1,2,...,wm+1,N)
w m + 1 , i = w m , i z m e − α m y i G m ( x i ) , i = 1 , 2 , . . . , N w_{m+1,i} = \frac{w_{m,i}}{z_{m}}e^{-\alpha_{m}y_{i}G_{m}(x_{i})}, i=1,2,...,N wm+1,i=zmwm,ie−αmyiGm(xi),i=1,2,...,N
其中 z m z_{m} zm是规范化因子,目的是使得 D m + 1 D_{m+1} Dm+1成了一个分布概率(这个不重要的,不理解也没关系)
z m = ∑ i = 1 N w m , i e − α m y i G m ( x i ) z_{m} = \sum_{i=1}^{N}w_{m,i}e^{-\alpha_{m}y_{i}G_{m}(x_{i})} zm=i=1∑Nwm,ie−αmyiGm(xi)
所以权重分布可以表示为:
w m + 1 , i = { w m , i z m e − α m G m ( x i ) = y i w m , i z m e α m G m ( x i ) ≠ y i w_{m+1,i}=\left\{ \begin{aligned} \frac{w_{m,i}}{z_{m}}e^{-\alpha_{m}} & & G_{m}(x_{i})=y_{i}\\ \frac{w_{m,i}}{z_{m}}e^{\alpha_{m}}& & G_{m}(x_{i})\ne y_{i}\\ \end{aligned} \right. wm+1,i=⎩ ⎨ ⎧zmwm,ie−αmzmwm,ieαmGm(xi)=yiGm(xi)=yi
由上式可知,被误分类的样本的权重被扩大,正确分类的样本的权重会缩小。相比而言(上面的式子/下面的式子)放大倍数是 1 − e m e m \frac{1-e_{m}}{e_{m}} em1−em。因此是的误分类样本在下一轮学习起到更大的作用,不改变所给对样本数据而不敢改变权重分布。 -
构建弱分类器的线性组合:
f ( x ) = ∑ m = 1 M α m G m ( x ) f(x) = \sum_{m=1}^{M}\alpha_{m}G_{m}(x) f(x)=m=1∑MαmGm(x)
得到最后的强分类器:
G ( x ) = s i g n ( f ( x ) ) = s i g n ( ∑ m = 1 M α m G m ( x ) ) G(x) = sign(f(x)) =sign(\sum_{m=1}^{M}\alpha_{m}G_{m}(x)) G(x)=sign(f(x))=sign(m=1∑MαmGm(x))
Adaboost利用向前算法的证明
Adaboost算法是一个加法模型,损失函数是指数函数:
L
(
y
,
f
(
x
)
)
=
e
−
y
f
(
x
)
L(y,f(x))=e^{-yf(x)}
L(y,f(x))=e−yf(x)
假设经过了
m
−
1
m-1
m−1轮迭代前向算法已经得到了:
f
m
−
1
(
x
)
=
f
m
−
2
(
x
)
+
α
m
−
1
G
m
−
1
(
x
)
f_{m-1}(x) = f_{m-2}(x)+\alpha_{m-1}G_{m-1}(x)
fm−1(x)=fm−2(x)+αm−1Gm−1(x)
在第
m
m
m轮迭代得到
α
m
\alpha_{m}
αm,
G
m
(
x
)
G_{m}(x)
Gm(x)和
f
m
(
x
)
f_{m}(x)
fm(x):
f
m
(
x
)
=
f
m
−
1
(
x
)
+
α
m
G
m
(
x
)
f_{m}(x) = f_{m-1}(x)+\alpha_{m}G_{m}(x)
fm(x)=fm−1(x)+αmGm(x)
此时,
α
m
\alpha_{m}
αm,
G
m
(
x
)
G_{m}(x)
Gm(x)使得
f
m
(
x
)
f_{m}(x)
fm(x)在训练数据
T
T
T上的损失函数最小。
(
α
m
,
G
m
(
x
)
)
=
arg min
α
,
G
∑
i
=
1
N
e
−
y
i
(
f
m
−
1
(
x
i
)
−
α
m
G
m
(
x
i
)
)
(8)
(\alpha_{m},G_{m}(x)) = \argmin_{\alpha,G}\sum_{i=1}^{N}e^{-y_{i}(f_{m-1(x_{i})-\alpha_{m}G_{m}(x_{i})})} \tag{8}
(αm,Gm(x))=α,Gargmini=1∑Ne−yi(fm−1(xi)−αmGm(xi))(8)
将
(
8
)
(8)
(8)内的指数里面整理得到:
(
α
m
,
G
m
(
x
)
)
=
arg min
α
,
G
∑
i
=
1
N
w
m
,
i
e
−
y
i
(
α
m
G
m
(
x
x
)
)
(9)
(\alpha_{m},G_{m}(x)) = \argmin_{\alpha,G}\sum_{i=1}^{N}w_{m,i}e^{-y_{i}(\alpha_{m}G_{m}(x_{x}))} \tag{9}
(αm,Gm(x))=α,Gargmini=1∑Nwm,ie−yi(αmGm(xx))(9)
其中,
w
m
,
i
=
e
−
y
i
f
m
−
1
(
x
i
)
w_{m,i}=e^{-y_{i}f_{m-1}(x_{i})}
wm,i=e−yifm−1(xi)与
α
m
\alpha_{m}
αm和
G
m
(
x
)
G_{m}(x)
Gm(x)无关,但是与
f
m
−
1
f_{m-1}
fm−1有关,因此这个指与求解无关,但是又会随着每一轮的迭代而不同。
现在使得 ( 9 ) (9) (9)最小就可以求出 α m \alpha_{m} αm和 G m ( x ) G_{m}(x) Gm(x)的最有解了,假设他们的最优解分别为 α ⋆ \alpha^{\star} α⋆和 G m ⋆ ( x ) G_{m}^{\star}(x) Gm⋆(x)。
我们先求 G m ⋆ ( x ) G_{m}^{\star}(x) Gm⋆(x):
G
m
⋆
(
x
)
G_{m}^{\star}(x)
Gm⋆(x)应该满足的是使得在第
m
m
m轮迭代的时候训练集上的加权误差最小(recall:adaboost每一轮通过调整样本权重实现着重学习上一轮学习错的样本),所以可以表示为:
G
m
⋆
(
x
)
=
arg min
G
∑
i
=
1
N
w
m
,
i
I
(
G
m
(
x
i
)
≠
y
i
)
G_{m}^{\star}(x)=\argmin_{G}\sum_{i=1}^{N}w_{m,i}I(G_{m}(x_{i})\ne y_{i})
Gm⋆(x)=Gargmini=1∑Nwm,iI(Gm(xi)=yi)
其中
w
m
,
i
=
e
−
y
i
f
m
−
1
(
x
i
)
w_{m,i}=e^{-y_{i}f_{m-1}(x_{i})}
wm,i=e−yifm−1(xi)
接下来我们求
α
⋆
\alpha^{\star}
α⋆:
(
9
)
(9)
(9)可以进行如下变换:
∑
i
=
1
N
w
m
,
i
e
y
i
α
m
G
m
(
x
i
)
=
∑
y
i
≠
G
m
(
x
i
)
w
m
,
i
e
α
+
∑
y
i
=
G
m
(
x
i
)
w
m
,
i
e
−
α
=
(
e
α
−
e
−
α
)
+
∑
i
=
1
N
w
m
,
i
I
(
G
m
(
x
i
)
≠
y
i
)
+
e
α
∑
i
=
1
N
w
m
,
i
(10)
\begin{aligned} \sum_{i=1}^{N}w_{m,i}e^{y_{i}\alpha_{m}G_{m}(x_{i})}&=\sum_{y_{i}\ne G_{m}(x_{i})}w_{m,i}e^{\alpha}+\sum_{y_{i}=G_{m}(x_{i})}w_{m,i}e^{-\alpha} \\ &=(e^{\alpha}-e^{-\alpha})+\sum_{i=1}^{N}w_{m,i}I(G_{m}(x_{i})\ne y_{i})+e^{\alpha}\sum_{i=1}^{N}w_{m,i} \end{aligned} \tag{10}
i=1∑Nwm,ieyiαmGm(xi)=yi=Gm(xi)∑wm,ieα+yi=Gm(xi)∑wm,ie−α=(eα−e−α)+i=1∑Nwm,iI(Gm(xi)=yi)+eαi=1∑Nwm,i(10)
将
G
m
⋆
(
x
)
G_{m}^{\star}(x)
Gm⋆(x)带入
(
10
)
(10)
(10)并对
α
m
\alpha_{m}
αm求导,并使得倒数为0,可求出
α
⋆
\alpha^{\star}
α⋆:
α
⋆
=
1
2
l
o
g
1
−
e
m
e
m
\alpha^{\star}=\frac{1}{2}log\frac{1-e_{m}}{e_{m}}
α⋆=21logem1−em
其中
e
m
=
∑
i
=
1
N
w
m
,
i
I
(
G
m
(
x
i
)
≠
y
i
)
e_{m} = \sum_{i=1}^{N}w_{m,i}I(G_{m}(x_{i})\ne y_{i})
em=i=1∑Nwm,iI(Gm(xi)=yi)
BoostingTree
BoostingTree其实就是boosting里的一种情况,就是基模型是决策树,分类就是分类树,回归就是回归树。其可以表示为决策树的加法模型:
f
(
x
)
=
∑
m
=
1
M
T
(
x
,
Θ
m
)
(11)
f(x)=\sum_{m=1}^{M} T(x,\Theta_{m})\tag{11}
f(x)=m=1∑MT(x,Θm)(11)
其中
Θ
m
\Theta_{m}
Θm为决策树,
Θ
m
\Theta_{m}
Θm为其参数,
M
M
M为树的个数。
BoostingTree仍然可以采用前向分步算法。对于不同的问题,主要区别在于损失函数的形式,可以是mse、log损失、指数损失等。对于分类问题,提升树算法只需将Adaboost算法里的基分类器限制为二分类树即可。
对于回归问题,假设提升树使用的损失是mse,我们可以进行如下的推导:
对于已知的训练集
T
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
,
(
x
N
,
y
N
)
}
T=\{(x_{1},y_{1}),(x_{2},y_{2}),...,(x_{N},y_{N})\}
T={(x1,y1),(x2,y2),...,(xN,yN)},其中
x
i
∈
X
⊆
R
n
x_{i}\in X \subseteq R^{n}
xi∈X⊆Rn,X为输入空间,
y
i
∈
Y
⊆
R
n
y_{i}\in Y \subseteq R^{n}
yi∈Y⊆Rn,
Y
Y
Y为输出空间。如果将输入空间划分为
J
J
J个互不相交的区域
R
1
,
R
2
,
.
.
.
.
,
R
J
R_{1},R_{2},....,R_{J}
R1,R2,....,RJ,并且在每个区域上确定输出的常量
c
j
c_{j}
cj,那么回归树就可以表示为:
T
(
x
,
Θ
)
=
∑
j
=
1
J
c
j
I
(
x
∈
R
j
)
(12)
T(x,\Theta)=\sum_{j=1}^{J}c_{j}I(x\in R_{j}) \tag{12}
T(x,Θ)=j=1∑JcjI(x∈Rj)(12)
其中
Θ
=
{
(
R
1
,
c
1
)
,
(
R
2
,
c
2
)
,
.
.
.
,
(
R
J
,
c
J
)
,
}
\Theta=\{(R_{1},c_{1}),(R_{2},c_{2}),...,(R_{J},c_{J}),\}
Θ={(R1,c1),(R2,c2),...,(RJ,cJ),}表示区域划分和区域上的常量,
J
J
J表示回归树的复杂度(叶节点个数)
其实上面就是回归树的定义,这里咱们简单复习下回归树(如果对这个章节非常的熟悉,可以跳过)
一个回归树其实对应着一个空间上的划分,以及在划分区域上面的输出值,就是上面提到的
R
j
R_{j}
Rj和
c
j
c_{j}
cj,
R
j
R_{j}
Rj好理解,就是利用特征值划分的区域,可以理解为子节点(叶节点)。
c
j
c_{j}
cj就是叶节点的输出值,其实就是在叶节点里所有的样本
y
i
y_{i}
yi的均值(后面在叙述过程中他也被叫做得分,划分确定了这个值也就定了),它可以表示为:
c
j
=
a
v
g
(
y
i
∣
x
i
∈
R
j
)
c_{j} = avg(y_{i}|x_{i}\in R_{j})
cj=avg(yi∣xi∈Rj)
空间的划分我们往往采用启发式的方法(离散特征和连续特征都可以按照下面的方法考虑,一般来说对于离散特征我们可以直接按照离散值划分区域就行,但是二叉树的离散特征按照下面的方法进行)
选择第
a
a
a个特征
x
(
a
)
x^{(a)}
x(a),以这个特征的值
s
s
s来切分的话,我们可以定义两个区域:
R
1
(
a
,
s
)
=
{
x
∣
x
(
a
)
≤
s
}
和
R
2
(
a
,
s
)
=
{
x
∣
x
(
a
)
>
s
}
R_{1}(a,s)=\{x|x_{(a)}\le s\}和R_{2}(a,s)=\{x|x_{(a)}> s\}
R1(a,s)={x∣x(a)≤s}和R2(a,s)={x∣x(a)>s}
对应的
c
1
=
a
v
g
(
y
i
∣
x
i
∈
R
1
)
和
c
2
=
a
v
g
(
y
i
∣
x
i
∈
R
2
)
c_{1} = avg(y_{i}|x_{i}\in R_{1})和c_{2} = avg(y_{i}|x_{i}\in R_{2})
c1=avg(yi∣xi∈R1)和c2=avg(yi∣xi∈R2)
这么划分好理解的,如何确定哪个特征的哪个值作为最后的切分点
s
s
s呢?其实只需要
x
(
a
)
x^{(a)}
x(a)和
s
s
s可以满足:
min
a
,
s
[
min
c
1
∑
x
i
⊆
R
1
(
a
,
s
)
(
y
i
−
c
1
)
2
+
min
c
2
∑
x
i
⊆
R
2
(
a
,
s
)
(
y
i
−
c
2
)
2
]
\min_{a,s}[\min_{c_{1}}\sum_{x_{i}\subseteq R_{1}(a,s)}(y_{i}-c_{1})^2+\min_{c_{2}}\sum_{x_{i}\subseteq R_{2}(a,s)}(y_{i}-c_{2})^2]
a,smin[c1minxi⊆R1(a,s)∑(yi−c1)2+c2minxi⊆R2(a,s)∑(yi−c2)2]
为了方便,下面也给出回归树的算法(后面会连同boosting tree给一个李航的统计学方法的例子)
输入:训练数据集
D
D
D
输出:回归树
f
(
x
)
f(x)
f(x)
在训练集所在的输入空间中,递归的将每个区域划分为2个子区域并决定每个区域上的输出值,构建二叉树。
(1)选择最优切分特征
a
a
a和切分点
s
s
s,求解:
min
a
,
s
[
min
c
1
∑
x
i
⊆
R
1
(
a
,
s
)
(
y
i
−
c
1
)
2
+
min
c
2
∑
x
i
⊆
R
2
(
a
,
s
)
(
y
i
−
c
2
)
2
]
(13)
\min_{a,s}[\min_{c_{1}}\sum_{x_{i}\subseteq R_{1}(a,s)}(y_{i}-c_{1})^2+\min_{c_{2}}\sum_{x_{i}\subseteq R_{2}(a,s)}(y_{i}-c_{2})^2] \tag{13}
a,smin[c1minxi⊆R1(a,s)∑(yi−c1)2+c2minxi⊆R2(a,s)∑(yi−c2)2](13)
遍历所有特征,对于固定的切分特征
a
a
a扫描所有切分值
s
s
s,选择
(
13
)
(13)
(13)最小的
(
a
,
s
)
(a,s)
(a,s)对。
(2)用选定的对
(
a
,
s
)
(a,s)
(a,s)划分区域并决定输出值:
R
1
(
a
,
s
)
=
{
x
∣
x
(
a
)
≤
s
}
和
R
2
(
a
,
s
)
=
{
x
∣
x
(
a
)
>
s
}
R_{1}(a,s)=\{x|x_{(a)}\le s\}和R_{2}(a,s)=\{x|x_{(a)}> s\}
R1(a,s)={x∣x(a)≤s}和R2(a,s)={x∣x(a)>s}
c
j
=
1
N
j
∑
x
i
⊆
R
1
(
a
,
s
)
y
i
x
i
∈
R
j
c_{j}=\frac{1}{N_{j}}\sum_{x_{i}\subseteq R_{1}(a,s)}y_{i} \qquad x{i} \in R_{j}
cj=Nj1xi⊆R1(a,s)∑yixi∈Rj
(3)连续对两个子区间调用(1)和(2)直至满足停止条件;
(4)将输入空间划分为
J
J
J个区域
R
1
,
R
2
,
.
.
.
,
R
J
R_{1},R_{2},...,R_{J}
R1,R2,...,RJ生成决策树:
T
(
x
,
Θ
)
=
∑
j
=
1
J
c
j
I
(
x
∈
R
j
)
T(x,\Theta)=\sum_{j=1}^{J}c_{j}I(x\in R_{j})
T(x,Θ)=j=1∑JcjI(x∈Rj)
OK回归整体,提升树的前向分步算法如下:
初始化:
f
0
(
x
)
=
0
f_{0}(x) = 0
f0(x)=0
第
m
m
m次迭代:
f
m
(
x
)
=
f
m
−
1
(
x
)
+
T
(
x
,
Θ
)
,
m
=
1
,
2
,
.
.
.
,
M
f_{m}(x)=f_{m-1}(x)+T(x,\Theta),\qquad m=1,2,...,M
fm(x)=fm−1(x)+T(x,Θ),m=1,2,...,M
此时
f
m
−
1
(
x
)
f_{m-1}(x)
fm−1(x)是已知的,需要求解:
Θ
m
⋆
=
arg min
Θ
m
∑
i
=
1
N
L
(
y
i
,
f
m
−
1
(
x
i
)
+
T
(
x
i
,
Θ
m
)
)
(14)
\Theta_{m}^{\star} = \argmin_{\Theta_{m}}\sum_{i=1}^{N}L(y_{i},f_{m-1}(x_{i})+T(x_{i},\Theta_{m})) \tag{14}
Θm⋆=Θmargmini=1∑NL(yi,fm−1(xi)+T(xi,Θm))(14)
因为回归问题,我们使用mse作为损失函数
L
(
y
,
f
(
x
)
)
=
(
y
−
f
(
x
)
)
2
L(y,f(x))=(y-f(x))^2
L(y,f(x))=(y−f(x))2,所以
(
14
)
(14)
(14)中的损失函数
L
(
y
,
f
(
x
)
)
L(y,f(x))
L(y,f(x))变成:
L
(
y
,
f
m
−
1
(
x
)
+
T
(
x
,
Θ
)
)
=
[
y
−
(
f
m
−
1
(
x
)
+
T
(
x
,
Θ
)
)
]
2
=
(
r
−
T
(
x
,
Θ
)
)
2
\begin{aligned} L(y, f_{m-1}(x)+T(x,\Theta)) &= [y-(f_{m-1}(x)+T(x,\Theta))]^2 \\ &=(r-T(x,\Theta))^2 \end{aligned}
L(y,fm−1(x)+T(x,Θ))=[y−(fm−1(x)+T(x,Θ))]2=(r−T(x,Θ))2
其中
r
=
y
−
f
m
−
1
(
x
)
(15)
r=y-f_{m-1}(x) \tag{15}
r=y−fm−1(x)(15)
由此可以看出当前模型拟合的是上一次迭代的残差,所以回归提升树可以理解为:每一轮基模型拟合的是上一轮的残差。
现在我们给出整个的回归提升树算法的流程:
输入:训练集数据
T
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
,
(
x
N
,
y
N
)
}
T=\{(x_{1},y_{1}),(x_{2},y_{2}),...,(x_{N},y_{N})\}
T={(x1,y1),(x2,y2),...,(xN,yN)},其中
x
i
∈
X
⊆
R
n
x_{i}\in X \subseteq R^{n}
xi∈X⊆Rn,
y
i
∈
Y
⊆
R
y_{i} \in Y \subseteq R
yi∈Y⊆R
输出:提升回归树
f
(
x
)
f(x)
f(x)
(1)初始化
f
0
(
x
)
=
0
f_{0}(x)=0
f0(x)=0
(2)对
m
=
1
,
2
,
.
.
.
,
M
m=1,2,...,M
m=1,2,...,M
a)根据
(
15
)
(15)
(15)计算残差:
r
m
,
i
=
y
i
−
f
m
−
1
(
x
i
)
i
=
1
,
2
,
.
.
.
,
M
r_{m,i}=y_{i}-f_{m-1}(x_{i}) \qquad i=1,2,...,M
rm,i=yi−fm−1(xi)i=1,2,...,M
b) 拟合残差
r
m
,
i
r_{m,i}
rm,i学习一颗回归树
T
(
x
,
Θ
m
)
T(x,\Theta_{m})
T(x,Θm)
c)更新
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)
(3)得到提升回归树
f
(
x
)
=
∑
m
=
1
M
T
(
x
,
Θ
m
)
f(x)=\sum_{m=1}^{M}T(x,\Theta_{m})
f(x)=∑m=1MT(x,Θm)
下面插播一段统计学方法里一个回归提升树的例子:
其实回归树可以做分类问题,只是损失函数不能用mse了,需要其他的损失函数。但是并不是所有的损失函数都可以表示成残差的形式,所以就需要有一些东西代替残差,这就有了GBDT。
GBDT
简单理解的话,GBDT就是上面介绍的BoostingTree,只是利用第
m
−
1
m-1
m−1轮迭代的损失函数的梯度近似代替残差。第
m
m
m轮来拟合这个梯度:
−
[
∂
L
(
y
,
f
(
x
i
)
)
∂
f
(
x
i
)
]
f
(
x
)
=
f
m
−
1
(
x
)
-[\frac{\partial L(y,f(x_{i}))}{\partial f(x_{i})}]_{f(x)=f_{m-1}(x)}
−[∂f(xi)∂L(y,f(xi))]f(x)=fm−1(x)
下面给出GBDT的算法流程:
输入:训练集数据
T
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
,
(
x
N
,
y
N
)
}
T=\{(x_{1},y_{1}),(x_{2},y_{2}),...,(x_{N},y_{N})\}
T={(x1,y1),(x2,y2),...,(xN,yN)},其中
x
i
∈
X
⊆
R
n
x_{i}\in X \subseteq R^{n}
xi∈X⊆Rn,
y
i
∈
Y
⊆
R
y_{i} \in Y \subseteq R
yi∈Y⊆R。损失函数
L
(
y
,
f
(
x
)
)
L(y,f(x))
L(y,f(x))
输出: 提升树
f
(
x
)
f(x)
f(x)
- 初始化 f 0 ( x ) f_{0}(x) f0(x),这里初始化可以是0也可以不是0
- 对
m
=
1
,
2
,
.
.
,
M
m=1,2,..,M
m=1,2,..,M
a)对 n = 1 , 2 , . . . , N n=1,2,...,N n=1,2,...,N,计算:
r m , i = − [ ∂ L ( y , f ( x i ) ) ∂ f ( x i ) ] f ( x ) = f m − 1 ( x ) (16) r_{m,i} = -[\frac{\partial L(y,f(x_{i}))}{\partial f(x_{i})}]_{f(x)=f_{m-1}(x)} \tag{16} rm,i=−[∂f(xi)∂L(y,f(xi))]f(x)=fm−1(x)(16)
b)对 r m , i r_{m,i} rm,i拟合一个回归树得到第 m m m棵树的叶节点区域 R m , j , j = 1 , 2 , . . . , J R_{m,j},j=1,2,...,J Rm,j,j=1,2,...,J
c)对 j = 1 , 2 , . . . , J j=1,2,...,J j=1,2,...,J计算区域内的预测值(下面的第一个式子其实就是回归树的求解过程)
c m , j = arg min c ∑ x ∈ R j L ( y i , f m − 1 ( x i ) + c ) c_{m,j} = \argmin_{c}\sum_{x\in R_{j}}L(y_{i},f_{m-1}(x_{i})+c) cm,j=cargminx∈Rj∑L(yi,fm−1(xi)+c)
T ( x , Θ ) = ∑ j = 1 J c j I ( x ∈ R j ) T(x,\Theta) = \sum_{j=1}^{J}c_{j}I(x\in R_{j}) T(x,Θ)=j=1∑JcjI(x∈Rj)
d)更新
f m ( x ) = f m − 1 ( x ) + T ( x , Θ ) = f m − 1 + ∑ j = 1 J c j I ( x ∈ R j ) f_{m}(x)=f_{m-1}(x)+T(x,\Theta)=f_{m-1}+ \sum_{j=1}^{J}c_{j}I(x\in R_{j}) fm(x)=fm−1(x)+T(x,Θ)=fm−1+j=1∑JcjI(x∈Rj) - 得到回归树
f ( x ) = ∑ m = 1 M T ( x , Θ ) = ∑ m = 1 M ∑ j = 1 J c j I ( x ∈ R j ) (17) f(x) = \sum_{m=1}^{M}T(x,\Theta)= \sum_{m=1}^{M}\sum_{j=1}^{J}c_{j}I(x\in R_{j}) \tag{17} f(x)=m=1∑MT(x,Θ)=m=1∑Mj=1∑JcjI(x∈Rj)(17)
现在我们推导下GBDT:
GBDT也可以用加法模型表示,在第
m
m
m轮迭代的时候:
f
m
(
x
)
=
f
m
−
1
(
x
)
+
T
(
x
,
Θ
)
f_{m}(x)=f_{m-1}(x)+T(x,\Theta)
fm(x)=fm−1(x)+T(x,Θ)
利用前向分步算法优化该模型,现在只需考虑加上一个
T
(
x
,
Θ
)
T(x,\Theta)
T(x,Θ)使得
L
(
y
,
f
m
(
x
)
)
L(y,f_{m}(x))
L(y,fm(x))最小,即:
T
(
x
,
Θ
)
=
arg min
T
(
x
,
Θ
)
L
(
y
,
f
m
−
1
(
x
)
+
T
(
x
,
Θ
)
)
T(x,\Theta)=\argmin_{T(x,\Theta)}L(y,f_{m-1}(x)+T(x,\Theta))
T(x,Θ)=T(x,Θ)argminL(y,fm−1(x)+T(x,Θ))
这个很难找到最小值,所以我们利用泰勒展开式试试:
recall:
f
(
x
+
Δ
x
)
≈
f
(
x
)
+
f
′
(
x
)
Δ
x
f(x+\Delta x) \approx f(x)+f'(x)\Delta x
f(x+Δx)≈f(x)+f′(x)Δx
L
(
y
,
f
m
−
1
(
x
)
+
T
(
x
,
Θ
)
)
≈
L
(
y
,
y
m
−
1
(
x
)
)
+
∂
L
(
y
,
f
m
−
1
(
x
)
)
∂
f
m
−
1
(
x
)
T
(
x
,
Θ
)
(18)
L(y,f_{m-1}(x)+T(x,\Theta)) \approx L(y,y_{m-1}(x))+\frac{\partial L(y,f_{m-1}(x))}{\partial f_{m-1}(x)}T(x,\Theta) \tag{18}
L(y,fm−1(x)+T(x,Θ))≈L(y,ym−1(x))+∂fm−1(x)∂L(y,fm−1(x))T(x,Θ)(18)
目前我们要使得
(
18
)
(18)
(18)最小,因为
L
(
y
,
f
m
−
1
(
x
)
)
L(y,f_{m-1}(x))
L(y,fm−1(x))是个常数,那么就应该使
∂
L
(
y
,
f
m
−
1
(
x
)
)
∂
f
m
−
1
(
x
)
T
(
x
,
Θ
)
\frac{\partial L(y,f_{m-1}(x))}{\partial f_{m-1}(x)}T(x,\Theta)
∂fm−1(x)∂L(y,fm−1(x))T(x,Θ)最小就行了。 怎么是它最小呢?我们可以按照向量的想法去考虑:
∂
L
(
y
,
f
m
−
1
(
x
)
)
∂
f
m
−
1
(
x
)
\frac{\partial L(y,f_{m-1}(x))}{\partial f_{m-1}(x)}
∂fm−1(x)∂L(y,fm−1(x))和
T
(
x
,
Θ
)
T(x,\Theta)
T(x,Θ)都是向量,
∂
L
(
y
,
f
m
−
1
(
x
)
)
∂
f
m
−
1
(
x
)
T
(
x
,
Θ
)
\frac{\partial L(y,f_{m-1}(x))}{\partial f_{m-1}(x)}T(x,\Theta)
∂fm−1(x)∂L(y,fm−1(x))T(x,Θ)是两个向量的内积,也就是
∣
∂
L
(
y
,
f
m
−
1
(
x
)
)
∂
f
m
−
1
(
x
)
∣
×
∣
T
(
x
,
Θ
)
∣
×
c
o
s
(
θ
)
|\frac{\partial L(y,f_{m-1}(x))}{\partial f_{m-1}(x)}|\times |T(x,\Theta)| \times cos(\theta)
∣∂fm−1(x)∂L(y,fm−1(x))∣×∣T(x,Θ)∣×cos(θ)。那么只有他们的方向相反(
c
o
s
(
θ
)
=
−
1
cos(\theta)=-1
cos(θ)=−1)的时候内积才是最小的。此时
T
(
x
,
Θ
)
=
−
∂
L
(
y
,
f
m
−
1
(
x
)
)
∂
f
m
−
1
(
x
)
T(x,\Theta)=-\frac{\partial L(y,f_{m-1}(x))}{\partial f_{m-1}(x)}
T(x,Θ)=−∂fm−1(x)∂L(y,fm−1(x))。
所以我们可以认为每轮迭代时, f m ( x ) = f m − 1 ( x ) + T ( x , Θ ) f_{m}(x)=f_{m-1}(x)+T(x,\Theta) fm(x)=fm−1(x)+T(x,Θ)才会使损失函数下降最快,也就是在第 m m m轮迭代时损失函数达到最小。此时 T ( x , Θ ) T(x,\Theta) T(x,Θ)就在拟合损失函数梯度的负方向。(所以我们说 T ( x , Θ ) T(x,\Theta) T(x,Θ)是在拟合上一轮的梯度,也就是拿梯度当残差是非常OK的。)
对于整体求解 f ( x ) = ∑ m = 1 M T ( x , Θ ) f(x)=\sum_{m=1}^{M}T(x,\Theta) f(x)=∑m=1MT(x,Θ)的时候,我们其实用到的就是梯度下降的思想,只不过原来梯度下降是在更新模型的参数(在实数空间迭代),GBDT是在更新新的树(在函数空间迭代)。
这个也证明了其实GBDT在用类似梯度下降的方法求解( ( 18 ) (18) (18)其实就是梯度下降的形式)。因为不再是求一个数了,而是求一个函数所以这个方法叫做gradient boosting。
Shrinkage:这个是GBDT避免过拟合的一个方法。主要思想是:每次走一小步逐渐逼近结果要比每次走一大步很快逼近结果更不容易过拟合。即他不完全信任一棵残差树,而是认为每一棵树只学到了真理的一小部分,累加的时候也只累加一小部分。通过更多的学习来弥补不足。公式表示为: f m ( x ) = f m − 1 ( x ) + ε T ( x , Θ ) , 0 < ε < 1 f_{m}(x)=f_{m-1}(x)+\varepsilon T(x,\Theta), 0<\varepsilon<1 fm(x)=fm−1(x)+εT(x,Θ),0<ε<1
GBDT可以解决线性和非线性的回归或分类问题。准确度也很高。不需要做特征归一化、自动做特征选择、模型解释也很好、可以适用多种损失函数。但是模型复杂度比较高,比较慢而且不支持并行化(因为基模型之间是相互影响的,只能在训练样本层面上进行并行)。不适合高维系数矩阵。
树模型有以下优点:
- 可解释性强
- 可处理混合类型特征(离散和连续)
- 不用进行归一化
- 有特征组合作用;
- 模型可处理缺失值
- 与异常值有鲁棒性
- 可扩展性强,
缺点:
- 缺乏平滑性(回归预测时输出值只能是若干种数值);
- 不适合处理高维稀疏数据
Xgboost
Xgboost是传统GBDT的进阶版本,在性能上有了明显提升。传统的GBDT利用的是损失函数的一阶泰勒展开进行的推导,而Xgboost用的是二阶泰勒展开进行的推导,并在损失函数后面加上正则项,降低整体模型复杂度,使模型更不容易过拟合。
首先给出损失函数(这里的符号和之前的不同,沿用的是陈天奇paper中的符号)。
再第
t
t
t轮迭代时,目标函数(其实就是损失函数)是:
o
b
j
(
t
)
=
∑
i
=
1
n
l
(
y
i
,
y
^
(
t
)
)
+
∑
j
=
1
t
Ω
(
f
j
)
(20)
obj^{(t)} =\sum_{i=1}^{n}l(y_{i},\hat y^{(t)})+\sum_{j=1}^{t}\Omega(f_{j}) \tag{20}
obj(t)=i=1∑nl(yi,y^(t))+j=1∑tΩ(fj)(20)
可以看到目标函数有两部分,前面是GBDT的损失函数,后面是L2正则项。此时加法模型:
y
^
i
(
t
)
=
y
^
i
(
t
−
1
)
+
f
t
(
x
i
)
(21)
\hat y_{i}^{(t)} = \hat y_{i}^{(t-1)}+f_{t}(x_{i}) \tag{21}
y^i(t)=y^i(t−1)+ft(xi)(21)
其中:
y
^
i
(
t
)
\hat y_{i}^{(t)}
y^i(t)是第
t
t
t轮的模型;
f
t
(
x
i
)
f_{t}(x_{i})
ft(xi)是这一轮要确定的树;
∑
j
=
1
t
Ω
(
f
j
)
\sum_{j=1}^{t}\Omega(f_{j})
∑j=1tΩ(fj)是模型的复杂度,即正则项。这里的
Ω
(
f
j
)
\Omega(f_{j})
Ω(fj)是未知的,
∑
j
=
1
t
−
1
Ω
(
f
j
)
\sum_{j=1}^{t-1}\Omega(f_{j})
∑j=1t−1Ω(fj)是已知的(因为已经迭代过了)。
∑
i
=
1
n
l
(
y
i
,
y
^
(
t
)
)
\sum_{i=1}^{n}l(y_{i},\hat y^{(t)})
∑i=1nl(yi,y^(t))是损失函数。
将
(
21
)
(21)
(21)代入
(
20
)
(20)
(20)得到:
o
b
j
(
t
)
=
∑
i
=
1
n
l
(
y
i
,
y
^
(
t
−
1
)
+
f
t
(
x
i
)
)
+
Ω
(
f
j
)
+
c
o
n
s
t
a
n
t
(22)
obj^{(t)}=\sum_{i=1}^{n}l(y_{i},\hat y^{(t-1)}+f_{t}(x_{i}))+\Omega(f_{j})+constant \tag{22}
obj(t)=i=1∑nl(yi,y^(t−1)+ft(xi))+Ω(fj)+constant(22)
(
22
)
(22)
(22)的constant是
∑
i
=
1
n
l
(
y
i
,
y
^
(
t
)
)
\sum_{i=1}^{n}l(y_{i},\hat y^{(t)})
∑i=1nl(yi,y^(t))。
接下来就要想办法最小化
o
b
j
(
t
)
obj^{(t)}
obj(t),但是这个跟之前的GBDT推导中遇到的问题一样:对于有些函数不能算梯度之类的,不好最小化。所以要讲
o
b
j
(
t
)
obj^{(t)}
obj(t)进行二阶泰勒展开。
recall
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
o
b
j
(
t
)
≈
∑
i
=
1
n
[
l
(
y
i
,
y
^
(
t
−
1
)
)
+
∂
y
^
i
(
t
−
1
)
l
(
y
i
,
y
^
i
(
t
−
1
)
)
f
t
(
x
i
)
+
1
2
∂
y
^
i
(
t
−
1
)
2
l
(
y
i
,
y
^
i
(
t
−
1
)
)
f
t
2
(
x
i
)
]
+
Ω
(
f
t
)
+
c
o
n
s
t
a
n
t
(23)
obj^{(t)} \approx \sum_{i=1}^{n}[l(y_{i},\hat y^{(t-1)})+\partial_{\hat y_{i}^{(t-1)}}l(y_{i},\hat y_{i}^{(t-1)})f_{t}(x_{i})+\frac{1}{2}\partial_{\hat y_{i}^{(t-1)}}^{2}l(y_{i},\hat y_{i}^{(t-1)})f_{t}^{2}(x_{i})]+\Omega(f_{t})+constant \tag{23}
obj(t)≈i=1∑n[l(yi,y^(t−1))+∂y^i(t−1)l(yi,y^i(t−1))ft(xi)+21∂y^i(t−1)2l(yi,y^i(t−1))ft2(xi)]+Ω(ft)+constant(23)
令
g
i
=
∂
y
^
i
(
t
−
1
)
l
(
y
i
,
y
^
i
(
t
−
1
)
)
g_{i}=\partial_{\hat y_{i}^{(t-1)}}l(y_{i},\hat y_{i}^{(t-1)})
gi=∂y^i(t−1)l(yi,y^i(t−1)),
h
i
=
∂
y
^
i
(
t
−
1
)
2
l
(
y
i
,
y
^
i
(
t
−
1
)
)
h_{i}=\partial_{\hat y_{i}^{(t-1)}}^{2}l(y_{i},\hat y_{i}^{(t-1)})
hi=∂y^i(t−1)2l(yi,y^i(t−1))并把常数项(constant和
l
(
y
i
,
y
^
(
t
−
1
)
)
l(y_{i},\hat y^{(t-1)})
l(yi,y^(t−1)))去掉,
(
23
)
(23)
(23)可以变成下面的形式:
L
(
t
)
=
∑
i
=
1
n
[
g
i
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
]
+
Ω
(
f
t
)
(24)
L^{(t)}=\sum_{i=1}^{n}[g_{i}f_{t}(x_{i})+\frac{1}{2}h_{i}f_{t}^{2}(x_{i})]+\Omega(f_{t}) \tag{24}
L(t)=i=1∑n[gift(xi)+21hift2(xi)]+Ω(ft)(24)
我们就要最小化
(
24
)
(24)
(24)就可以了,其中
g
i
g_{i}
gi和
h
i
h_{i}
hi已知,
f
t
(
x
)
f_{t}(x)
ft(x)未知,
Ω
(
f
t
)
\Omega(f_{t})
Ω(ft)也是未知的,但是这个跟
f
t
(
x
)
f_{t}(x)
ft(x)有关。接下来我们就定一下
f
t
(
x
)
f_{t}(x)
ft(x),其实就是定义树的结构(这个跟之前定义的一样,回归树可以定义为空间的划分和区域内的输出值)。这里的树是二叉树。
定义的树为:
f
t
(
x
)
=
w
q
(
x
)
,
w
∈
R
T
,
q
:
R
d
→
{
1
,
2
,
.
.
.
,
T
}
(25)
f_{t}(x) = w_{q(x)},\qquad w\in R^{T}, q:R^{d}\to\{1,2,...,T\} \tag{25}
ft(x)=wq(x),w∈RT,q:Rd→{1,2,...,T}(25)
其中
T
T
T是叶节点个数,
q
(
x
)
q(x)
q(x)是空间划分(之前的
R
j
R_{j}
Rj),
w
w
w是叶节点的得分(其实就是叶节点的输出值,我们之前的
c
j
c_{j}
cj)
接下来我们定义正则项(这里大神就是这么定义的,没有原因):
Ω
(
f
t
)
=
γ
T
+
1
2
λ
∑
j
T
w
j
2
(26)
\Omega(f_{t})=\gamma T+\frac{1}{2}\lambda \sum_{j}^{T}w_{j}^{2} \tag{26}
Ω(ft)=γT+21λj∑Twj2(26)
将
(
25
)
(25)
(25)和
(
26
)
(26)
(26)代入
(
24
)
(24)
(24)有:
L
(
t
)
=
∑
i
=
1
n
[
g
i
w
q
(
x
i
)
+
1
2
h
i
w
q
(
x
i
)
2
]
+
γ
T
+
1
2
λ
∑
j
T
w
j
2
(27)
L^{(t)}=\sum_{i=1}^{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}^{T}w_{j}^{2} \tag{27}
L(t)=i=1∑n[giwq(xi)+21hiwq(xi)2]+γT+21λj∑Twj2(27)
(
24
)
(24)
(24)有个问题:
∑
i
=
1
n
[
l
(
y
i
,
y
^
i
(
t
−
1
)
)
+
g
i
w
q
(
x
i
)
+
1
2
h
i
w
q
(
x
i
)
2
]
\sum_{i=1}^{n}[l(y_{i},\hat y_{i}^{(t-1)})+g_{i}w_{q(x_{i})}+\frac{1}{2}h_{i}w_{q(x_{i})}^{2}]
∑i=1n[l(yi,y^i(t−1))+giwq(xi)+21hiwq(xi)2]是样本累加,
∑
j
=
1
T
w
j
2
\sum_{j=1}^{T}w_{j}^{2}
∑j=1Twj2是叶节点的累加,如果不把两个统一,我们就没办法继续最小化了。所以我们在这里要定义每个叶节点的样本集合:
I
j
=
{
i
∣
q
(
x
i
)
=
j
}
(28)
I_{j}=\{ i|q(x_{i})=j\} \tag{28}
Ij={i∣q(xi)=j}(28)
定义
(
28
)
(28)
(28)是为了将样本累加变换到叶节点累加。把
(
28
)
(28)
(28)代入
(
27
)
(27)
(27)有:
L
(
t
)
=
∑
j
=
1
T
[
(
∑
i
∈
I
j
g
i
)
w
j
+
1
2
(
∑
i
∈
I
j
h
i
)
w
j
2
]
+
γ
T
+
1
2
λ
∑
j
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
(29)
\begin{aligned} L^{(t)} &= \sum_{j=1}^{T}[(\sum_{i \in I_{j}}g_{i})w_{j}+\frac{1}{2}(\sum_{i \in I_{j}}h_{i})w_{j}^{2}]+\gamma T+\frac{1}{2}\lambda \sum_{j}^{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} \tag{29}
L(t)=j=1∑T[(i∈Ij∑gi)wj+21(i∈Ij∑hi)wj2]+γT+21λj∑Twj2=j=1∑T[(i∈Ij∑gi)wj+21(i∈Ij∑hi+λ)wj2]+γT(29)
令
G
j
=
∑
i
∈
I
j
g
i
G_{j}=\sum_{i \in I_{j}}g_{i}
Gj=∑i∈Ijgi和
H
j
=
∑
i
∈
I
j
h
i
H_{j}=\sum_{i \in I_{j}}h_{i}
Hj=∑i∈Ijhi,
(
29
)
(29)
(29)可以写成:
L
(
t
)
=
∑
j
=
1
T
[
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
]
+
γ
T
(30)
L^{(t)} = \sum_{j=1}^{T}[G_{j}w_{j}+\frac{1}{2}(H_{j}+\lambda)w_{j}^{2}]+\gamma T \tag{30}
L(t)=j=1∑T[Gjwj+21(Hj+λ)wj2]+γT(30)
此时,
G
j
G_{j}
Gj和
H
j
H_{j}
Hj已知,如果树的结构
w
q
(
x
)
w_{q(x)}
wq(x)是确定的,那么叶节点个数
T
T
T就是确定的,
w
j
w_{j}
wj就是要求的未知数,此时
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
G_{j}w_{j}+\frac{1}{2}(H_{j}+\lambda)w_{j}^{2}
Gjwj+21(Hj+λ)wj2的结构是一个二次函数,如果求
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
G_{j}w_{j}+\frac{1}{2}(H_{j}+\lambda)w_{j}^{2}
Gjwj+21(Hj+λ)wj2的最小值,可以使
(
30
)
(30)
(30)对
w
j
w_{j}
wj求导,令导数为0即可:
∂
w
j
(
G
j
w
j
+
1
2
(
H
j
+
λ
)
w
j
2
)
=
0
\partial_{w_{j}}(G_{j}w_{j}+\frac{1}{2}(H_{j}+\lambda)w_{j}^{2})=0
∂wj(Gjwj+21(Hj+λ)wj2)=0
解得每个叶节点的最有分数(预测值)为:
w
j
⋆
=
−
G
j
H
j
+
λ
(31)
w_{j}^{\star}=-\frac{G_{j}}{H_{j}+\lambda} \tag{31}
wj⋆=−Hj+λGj(31)
将
(
31
)
(31)
(31)代入
(
30
)
(30)
(30)得到
L
(
t
)
L^{(t)}
L(t)的最小值:
L
(
t
)
⋆
=
−
1
2
∑
j
=
1
T
G
j
2
H
j
+
λ
+
γ
T
(32)
L^{(t) \star} = -\frac{1}{2}\sum_{j=1}^{T}\frac{G_{j}^{2}}{H_{j}+\lambda}+\gamma T \tag{32}
L(t)⋆=−21j=1∑THj+λGj2+γT(32)
此时我们是在树的结构确定的条件下得到的损失函数最小值和叶节点的最有预测值。但是我们并没有确定树的结构。所以接下来我们要确定树的结构
q
(
x
)
q(x)
q(x)
如果暴力穷举所有的树结构选择
L
(
t
)
⋆
L^{(t) \star}
L(t)⋆最小的,这种方法是不实现的,因为树的结构实在是太多了。所以我们采用贪心的方法:每次尝试分裂一个叶节点,计算分裂前后的的增益,选择增益最大的特征进行分类。对于一个叶节点进行分裂,分类前后的增益定义为:
G
a
i
n
=
G
L
2
H
L
+
λ
+
G
R
2
H
L
+
λ
−
G
L
2
+
G
H
2
H
L
+
H
R
+
λ
−
γ
(33)
Gain=\frac{G_{L}^{2}}{H_{L}+\lambda}+\frac{G_{R}^{2}}{H_{L}+\lambda}-\frac{G_{L}^{2}+G_{H}^{2}}{H_{L}+H_{R}+\lambda}-\gamma \tag{33}
Gain=HL+λGL2+HL+λGR2−HL+HR+λGL2+GH2−γ(33)
Gain越大,分裂后
L
(
t
)
L^{(t)}
L(t)减少的越多。所以当对每个叶节点分裂时,计算所有候选的特征的每一个可能的切分点对应的Gain,选择Gain最大的特征的那个切分点进行分裂。
下面给出树节点分裂的流程:
精确算法:遍历所有特征的所有可能的分割点,计算Gain,选择最大的(特征、切分点)去分割。
下图是精确算法的伪代码:
近似算法:对于每个特征,只考察分位点(比如上四分位、中位数、下四分位等,这个不是固定的,比如30%分为也可以的),为了减少计算复杂度,这里有两种方式计算:
- global:学习每棵树前,预先提出候选的切分点;
- local:每次分裂前,提出候选分裂点。
这种近似的算法在实际操作中,不是直接对feature进行分割,而是先对feature求二阶导数,然后再二阶导数上找分位点。二阶导实际上是损失函数对每棵树 f t ( x ) f_{t}(x) ft(x)的加权:
∑ i = 1 n 1 2 h i ( f t ( x i ) − g i h i ) 2 + Ω ( f t ) \sum_{i=1}^{n}\frac{1}{2}h_{i}(f_{t}(x_{i})-\frac{g_{i}}{h_{i}})^2+\Omega(f_{t}) i=1∑n21hi(ft(xi)−higi)2+Ω(ft)
下图是近似算法的伪代码:
近似算法的图例(以三分为为例)
求特征的二阶导之后再利用二阶导上的分位点进行切分:
无论是精确算法还是近似算法都需要对每个特征的所有取值进行排序,而我们的特征往往很多,所以非常费时间。
处理缺失值:
把含有缺失值的特征先分给左边的子节点,在分给右边的子节点,比较Gain哪个大,就把缺失值分到哪个节点。
缺失值的伪代码如下:
其他特性:
- Xgboost也会在训练每个模型的时候,进行训练集抽样和样本抽样(跟随机森林一样);
- 依然使用shrinkage;
- 支持自定义损失函数,
- 相比于GBDT,速度更快、容错更高、可以并行化。
LightGBM
LightGBM是更高效的GBDT,可以理解为是加了GOSS和EFB的GBDT。推导过程和Xgboost基本类似,也是加法模型加前向分步算法。GBDT和Xgboost都面临的问题是要寻找合适的切分点,这个非常耗时。lightGBM通过GOSS和EFB在保证准确率的同时大幅提升了速度。
在寻找合适的切分点时,最常用的方法是预排序。这个方法就是事先计算好某个特征可能要选的切分点,sklearn的GBDT就是预排序。还有一种方法叫做直方图法,它的主要思想是把连续的特征变成离散的分组,然后就在这些分组中找切分点,这样大幅提高了效率。Xgboost支持预排序和直方图,lightGBM支持直方图法。
下面就看看直方图的形象例子:
下面先介绍两个LightGBM改进的特性:
LightGBM的直方图法:
每次分裂时,遍历所有的叶节点对每个叶节点做如下:
- 对每个特征创建一个直方图(就是把特征值分为若干段,每一段是一个bin,然后将样本值划分到对应的bin中去。把连续值变成离散值)。直方图会存两个信息:a)每个bin中的样本的梯度;b)每个bin中的样本数 n n n。这一步需要遍历所有样本,把上面的统计量都放在对应的bin中。
- 对每一个特征,遍历所有的bin,对每个bin让其尝试做切分点:
a) 当某个bin作为切分点时,需要累加器左边至当前所有bin的梯度 S L S_{L} SL以及样本数 n L n_{L} nL。(此时相当于当前节点用了这个特征的这个bin进行了分裂,算出了左边子节点的累计梯度以及累计样本数和)
b) S R = S P − S L S_{R}=S_{P}-S_{L} SR=SP−SL; n R = n P − n L n_{R}=n_{P}-n_{L} nR=nP−nL 其中 S P S_{P} SP和 n P n_{P} nP分别为当前要分裂节点的累计梯度和累计样本数和(这两个值在上一轮迭代中已经算出来了)。
c) 利用a)和b)中算出的值求出此次分裂的增益:
G a i n = S L 2 n L + S R 2 n L − S P 2 n P Gain=\frac{S_{L}^{2}}{n_{L}}+\frac{S_{R}^{2}}{n_{L}}-\frac{S_{P}^2}{n_{P}} Gain=nLSL2+nLSR2−nPSP2
整个过程中选择增益最大的那个特征以及bin作为分裂特征和切分点。
下面是直方图算法的伪代码(这里的
Δ
l
o
s
s
\Delta loss
Δloss是上面说的Gain):
这里涉及到了一个lightGBM的优化:直方图加速差(一个叶节点的直方图可以由他的父节点的直方图和他兄弟的直方图作差得到)
直方图的优点(相比于预排序):内存占用小,增益的计算量小;
直方图缺点:不能选找到准确的切分点,准确率会差一些(但实验结果证明并没有差很多,但是会给整个模型带来更好的泛化,因为这种单棵树上的粗粒度切分点起到了正则化的作用,防止过拟合); 不能处理稀疏矩阵。
LightGBM的leaf-wise:
构建树有两种方式:level-wise和leaf-wise。Xgboost采用的是level-wise,lightGBM采用的是leaf-wise。
level-wise是同一层的所有节点都做分裂;leaf-wise选择增益最大的节点分裂,这样做容易过拟合。但是可以通过max_depth限制以防止过拟合。
Gradient-based One-side Sampling(GOSS):
这是一个在每轮迭代前,对训练样本进行采样的算法。在
t
−
1
t-1
t−1轮结束后,目标函数是
o
b
j
(
t
−
1
)
obj^{(t-1)}
obj(t−1)。每一个样本的梯度值都可以算出来。论文中发现,如果一个样本的梯度值很小,这样的样本的训练误差就很小,这样的样本已经被训练的很好了。反之一个样本的梯度很大,训练误差就会大,对整体训练误差的贡献就大,所以在下一轮迭代前可以根据梯度的大小进行采样这样训练就能更快。GOSS就是完成这个工作的。
- 将样本按照梯度的大小进行排序;
- 选梯度大的样本集和 A A A:取梯度大的Top a%的样本组成一个集和;
- 选择梯度小的样本集和 B B B:取剩下的样本集((1-a%)的样本)以b%的比率进行随机采样。
- 在选取分割点分类时,计算Gain的时候要分开计算:
recall:直方图的Gain计算: G a i n = S L 2 n L + S R 2 n L − S P 2 n P Gain=\frac{S_{L}^{2}}{n_{L}}+\frac{S_{R}^{2}}{n_{L}}-\frac{S_{P}^2}{n_{P}} Gain=nLSL2+nLSR2−nPSP2
其中, S L = S L , A + 1 − a b S L , B S_{L}=S_{L,A}+\frac{1-a}{b}S_{L,B} SL=SL,A+b1−aSL,B, S R = S R , A + 1 − a b S R , B S_{R}=S_{R,A}+\frac{1-a}{b}S_{R,B} SR=SR,A+b1−aSR,B, S P = S P , A + 1 − a b S P , B S_{P}=S_{P,A}+\frac{1-a}{b}S_{P,B} SP=SP,A+b1−aSP,B
S L , A , S R , A , S P , A S_{L,A},S_{R,A},S_{P,A} SL,A,SR,A,SP,A分别是左子节点、右子节点和当前节点的大梯度的结合的梯度和;
S L , B , S R , B , S P , B S_{L,B},S_{R,B},S_{P,B} SL,B,SR,B,SP,B分别是左子节点、右子节点和当前节点的小梯度的结合的梯度和;
1 − a b \frac{1-a}{b} b1−a为调节稀疏,这是为了保证抽样后,不太改变训练集的数据分布。注:微软发的论文中计算Gain的表达式不是这样的,这是我理解的写法。
论文中给出了一个定理:利用GOSS的GBDT并没有降低很多准确率,却大大提升了运算速度。
Exclusive Feature Bundling(EFB)
在特征维度很高的情况下,特征空间一般是稀疏的(即在某个样本上,特征不太可能同时取非零的值),我们可以利用这一点,可以几乎无损的降低特征维度,更确切的是降低构造特征直方图需要遍历特征的数量,这就是EFB的意义。
这里要解决两个问题:如何确定哪个特征合并在一起比较好;如何把这些特征合并在一起。第一个问题靠Greedy Bundling完成,第二个问题靠Merge Exclusive Features完成。
Greedy Bundling
这是利用图里面的着色问题解决。下面给出伪代码(不理解也不影响)
Merge Exclusive Features
这个就是把多个不为0的特征合并在一起,并且为了防止有值的特征在做直方图的时候重叠在一起,需要给每个特征一个offset(偏移量)使得不同的特征取值范围分开。比如要把feature A和featureB合并在一起,A的取值范围是
(
0
,
10
]
(0,10]
(0,10],B的取值范围是
(
0
,
20
]
(0,20]
(0,20]那么合并之前我们给B一个偏移量10,那么B的取值范围是
(
10
,
30
]
(10,30]
(10,30]
LightGBM的优点:
- 速度非常快;
- 内存使用率低;
- 准确率高;
- 支持并行化训练;
- 能够处理大规模数据
- 类别形变量不必提前做哑变量。
Catboost
Catboost是基于对称决策树(oblivious tree)的GBDT变种,相较于Xgboost和LightGBM提升了训练速度、解决了对类别型变量处理的问题,解决了梯度偏差和预测偏移的问题、提高了准确性和泛化能力。
这个算法的目标函数,计算损失函数等和Xgboost和LightGBM是一样的,所以我们也只说说它的特别的地方。
对类别型特征的处理
对于特征基数比较低的特征(比如性别、学历这样的可以枚举的类别较少的类别型特征)直接采用one-hot,这个过程是在训练时完成的,所以不需要做特征处理。
对于特征基数较多的特征(比如uid、所在城市等这种可以枚举非常非常多的类别特征)采用目标变量统计(TS,Catboost里面用的是greedyTS,原理是一样的)。
这种做法相较于LightGBM使用梯度的统计,计算速度更快,存储需求更少,信息损失也少。
目标变量统计(TS)
举个例子解释TS:我们解决的是一个二分类问题,有一个特征是性别={男、女}。我们先做个统计:假设我们的训练样本有100个,性别这个特征是男的样本有60个,其中
y
=
1
y=1
y=1的有10个。那么性别为男我们可以表示为
10
60
\frac{10}{60}
6010。其实可以看出TS就是在计算这个类别型特征中每个特征值对应的
y
y
y的均值。
其实上面的解释还有些问题:如果训练集变化,那么这个值也会变化。这样不是很开心的事情,所以我们加入先验知识。公式如下:
f
e
a
t
u
r
e
n
e
w
=
c
o
u
n
t
I
n
C
l
a
s
s
+
p
r
i
o
r
t
o
t
a
l
C
o
u
n
t
+
a
feature_new = \frac{countInClass+prior}{totalCount+a}
featurenew=totalCount+acountInClass+prior
c
o
u
n
t
I
n
C
l
a
s
s
countInClass
countInClass:当前特征值中
y
=
1
y=1
y=1的数量;
p
r
i
o
r
prior
prior:是鲜艳;
t
o
t
a
l
C
o
u
n
t
totalCount
totalCount:当前特征值的样本数量;
a
a
a:一个大于0的数,可以是1。
Catboost里实现了很多种greedyTS的变种,这里就不多做介绍了。有一点需要强调:Catboost在做greedyTS需要对训练数据进行多次shuffle。测试集的类别特征是用训练集的同一个类别特征的多个编码值平均得到的。
特征组合
Catboost还会把类别特征进行组合,这个在Xgboost和LightGBM也有类似操作。在类别特别多的时候,Catboost不会考虑所有的特征组合,只会考虑一部分的组合。它会用一种贪婪的想法:在选择第一个节点时,只会考虑一个特征,例如性别。在选择第二个节点的时候,会考虑和其他类别性特征的组合,选择其中最好的。
梯度偏差和预测偏移
这个问题在所有的GBDT的算法中都会出现,这个东西是源于GBDT每一步的迭代都会使用相同的数据,而且GBDT的树的计算是相互联系的,所以如果一棵树计算产生了偏差(梯度偏差:可以理解为在拟合过程中对梯度的有偏估计,因为训练数据和真实数据分布存在差异)这种偏差会不断累积,最后造成模型预测结果不好(预测的偏差,bias)。这个事情可以靠行列采样和正则化来缓解(Xgboost和lightGBM是用的这样的方法),CatBoost还采用了ordered boosting来缓解,但是这会非常慢,官网建议样本不超过5万。
优点:
- 速度快(使用cate_feature会慢很多);
- 准确性要比Xgboost和lightGBM要稍好些(如果数值型特征比较多,效果比lightGBM差一些);
- 鲁棒性好(默认参数就可以跑出一个还ok的结果,通过各种方式预防过拟合)
缺点:
- 对于类别型变量处理特别慢且费内存;
- 不同的随机数对模型有明显影响;
- 参数太多,文档太差了。
至此,我们关于集成树模型的知识梳理就到这了,可能后续还会出一篇关于用的包的。