集成学习–GBDT和XGBoost
GBDT和XGBoost是属于集成学习中的Boosting,相较于基本的AdaBoosting算法,这两个算法更加广泛的应用在各种比赛中。
GBDT
GBDT(Gradient Boosting Decision Tree)又称为梯度提升树,其是基于决策树或者回归树为单学习器的集成学习工具。GBDT的基本思想是拟合残差,残差简单的一种有 y i − f ( x i ) y_i-f(x_i) yi−f(xi),每个单学习器的输入是上个学习器学习所得的残差(除第一个学习器外),每次迭代都能使得所有数据的损失函数减少,足够多次的迭代后可以通过减少偏差来减少预测误差。
对于每个学习器,也就是分类树或者回归树,假设有 J J J个叶子节点,每个叶子节点分为 R j R_j Rj区域,学习函数为 h ( x ) = ∑ j = 1 J c j I ( x ∈ R j ) h(x)=\sum_{j=1}^Jc_jI(x\in R_j) h(x)=∑j=1JcjI(x∈Rj),意思就是如果 x ∈ R j x\in R_j x∈Rj,那么预测结果就是 c j c_j cj。GDBT是基于加法模型即学习器的线性组合,第t次学习的结果就是 f t ( x ) = f t − 1 ( x ) + h ( x ) f_t(x)=f_{t-1}(x)+h(x) ft(x)=ft−1(x)+h(x)。
对于第m个学习器 f m ( x ) f_m(x) fm(x)来说,如何选择特征进行分支,这就是分类树或者回归树的内容,特征的选择是基于使误差函数 f o r i = 1 t o m 有 L ( y i , f m − 1 ( x i ) + c ) for\space i=1\space to\space m\space 有L(y_i,f_{m-1}(x_i)+c) for i=1 to m 有L(yi,fm−1(xi)+c)最小。实现暴力遍历所有特征,假设以该特征为分支,所得到的预测结果加上之前的预测结果,使之损失函数最小。
那GBDT的梯度是哪里来的呢?其实残差就是梯度,定义 r i = ∂ L ∂ f ( x i ) r_i=\frac{\partial L}{\partial f(x_i)} ri=∂f(xi)∂L
对每个样本,就以 ( x 1 , r 1 ) , ( x 2 , r 2 ) , ⋯ , ( x m , r m ) (x_1,r_1),(x_2,r_2),\cdots,(x_m,r_m) (x1,r1),(x2,r2),⋯,(xm,rm) 作为输入继续学习。如果损失函数是均方差 L ( y i , f ( x i ) ) = 1 2 ∑ i = 1 m ( y i − f ( x i ) ) 2 L(y_i,f(x_i))=\frac{1}{2}\sum_{i=1}^m(y_i-f(x_i))^2 L(yi,f(xi))=21∑i=1m(yi−f(xi))2,即残差就是 y i − f ( x i ) y_i-f(x_i) yi−f(xi),整个学习器的模型会向着损失函数减少的梯度前进。
以均方差为损失函数,预测一个人的年龄,若一个人真实年龄为30岁,第一个学习器预测为20岁,残差为10岁,则以10岁为输入预测,第二个学习器预测为5岁,则两个学习器总预测为25岁,残差为5岁,继续学习预测为2岁,加上之前的结果预测为27岁,则一步步接近真实值。
以均方差为损失函数,GBDT算法步骤是
- 初始化第一颗树 f 0 ( x i ) = ∑ j = 1 J c j I ( x ∈ R j ) f_0(x_i)=\sum_{j=1}^Jc_jI(x\in R_j) f0(xi)=∑j=1JcjI(x∈Rj), 其 中 c j 为 区 域 R j 的 均 值 其中c_j为区域R_j的均值 其中cj为区域Rj的均值,且 1 2 ∑ i = 1 m ( y i − f 0 ( x i ) ) 2 \frac{1}{2}\sum_{i=1}^m(y_i-f_0(x_i))^2 21∑i=1m(yi−f0(xi))2取到最小值
- 取 r i = y i − f 0 ( x i ) r_i=y_i-f_0(x_i) ri=yi−f0(xi),以 ( x 1 , r 1 ) , ( x 2 , r 2 ) , ⋯ , ( x m , r m ) (x_1,r_1),(x_2,r_2),\cdots,(x_m,r_m) (x1,r1),(x2,r2),⋯,(xm,rm)为下一棵树的训练集
- 第m棵树的函数为 f m ( x i ) = ∑ j = 1 J c j I ( x ∈ R j ) f_m(x_i)=\sum_{j=1}^Jc_jI(x\in R_j) fm(xi)=∑j=1JcjI(x∈Rj), 其 中 c j 为 区 域 R j 的 均 值 其中c_j为区域R_j的均值 其中cj为区域Rj的均值,且 1 2 ∑ i = 1 m ( y i − ( f m − 1 ( x i ) + f m ( x i ) ) 2 \frac{1}{2}\sum_{i=1}^m(y_i-(f_{m-1}(x_i)+f_m(x_i))^2 21∑i=1m(yi−(fm−1(xi)+fm(xi))2取到最小值
- 当模型误差达到阈值或者迭代次数达到要求时,训练停止
注:不同的损失函数则会有不同的GDBT树
XGBoost
XGBoost是GBDT的改进版,普遍认为是学习性能较好的强学习器,据统计,在2015年Kaggle举办的机器学习比赛中,在29支获胜队伍中,有17支队伍使用了XGBoost算法
先说一下与GBDT相同的东西:
- 每个单学习器也是分类树或者回归树
- 整个模型是加法模型,即各个学习器的线性组合
- 同样是学习上一个学习器的预测残差
- 对于第m个学习器,目的都是使得损失函数 ∑ i = 1 m L ( y i , f m − 1 ( x i ) + f m ( x i ) ) \sum_{i=1}^mL(y_i,f_{m-1}(x_i)+f_m(x_i)) ∑i=1mL(yi,fm−1(xi)+fm(xi))最小
但既然是改进版,当然也会有许多更加优化的步骤
首先我们明确目标,是使得损失函数
∑
i
=
1
m
l
(
y
i
,
y
i
^
)
最
小
,
其
中
y
i
为
真
实
值
,
y
i
^
为
预
测
值
\sum_{i=1}^ml(y_i,\hat{y_i})最小,其中y_i为真实值,\hat{y_i}为预测值
i=1∑ml(yi,yi^)最小,其中yi为真实值,yi^为预测值
注:假设数据有m个样本
XGBoost独特的一点是损失函数要加上特殊的L2正则化防止过拟合
L
=
∑
i
=
1
m
l
(
y
i
,
y
i
^
)
+
∑
k
=
1
K
Ω
(
f
k
)
,
假
设
有
K
棵
树
,
即
K
个
学
习
器
Ω
(
f
k
)
=
γ
T
+
∑
j
=
1
T
λ
w
j
2
,
假
设
第
k
棵
树
有
T
个
叶
子
节
点
,
每
个
叶
子
节
点
的
取
值
为
w
t
(
同
G
B
D
T
中
的
c
j
)
这
个
正
则
化
可
以
理
解
为
不
要
使
得
T
(
叶
子
节
点
过
多
)
,
不
要
使
得
w
过
大
,
这
两
者
的
权
重
由
γ
和
λ
决
定
L=\sum_{i=1}^ml(y_i,\hat{y_i})+\sum_{k=1}^K\Omega(f_k),假设有K棵树,即K个学习器\\ \Omega(f_k)=\gamma T+\sum_{j=1}^T\lambda w_j^2,假设第k棵树有T个叶子节点,每个叶子节点的取值为w_t(同GBDT中的c_j)\\ 这个正则化可以理解为不要使得T(叶子节点过多),不要使得w过大,这两者的权重由\gamma和\lambda决定
L=i=1∑ml(yi,yi^)+k=1∑KΩ(fk),假设有K棵树,即K个学习器Ω(fk)=γT+j=1∑Tλwj2,假设第k棵树有T个叶子节点,每个叶子节点的取值为wt(同GBDT中的cj)这个正则化可以理解为不要使得T(叶子节点过多),不要使得w过大,这两者的权重由γ和λ决定
对于第t棵树而言,前面t-1棵树的正则化的部分是已知的,因为前面t-1棵树已经生成,每棵树的叶子节点个数和每个叶子节点的评分(即w)已知,所有上述式子变成
L
=
∑
i
=
1
m
l
(
y
i
,
y
i
^
)
+
Ω
(
f
t
)
+
C
L=\sum_{i=1}^ml(y_i,\hat{y_i})+\Omega(f_t)+C
L=i=1∑ml(yi,yi^)+Ω(ft)+C
常数C无关紧要,然后我们可以变形一下
L
=
∑
i
=
1
m
l
(
y
i
,
y
i
^
)
+
Ω
(
f
t
)
+
C
=
∑
i
=
1
m
l
(
y
i
,
y
i
^
t
−
1
+
f
t
(
x
i
)
)
+
γ
T
+
∑
j
=
1
T
λ
w
j
2
+
C
,
解
释
y
i
^
t
−
1
为
前
面
t
−
1
个
学
习
器
的
预
测
值
由
泰
勒
展
开
f
(
x
+
Δ
x
)
=
f
(
x
)
+
f
˙
(
x
)
Δ
x
+
1
2
f
¨
(
x
)
Δ
x
2
L
=
∑
i
=
1
m
(
l
(
y
i
,
y
i
^
t
−
1
)
+
l
˙
(
y
i
,
y
i
^
t
−
1
)
f
t
(
x
i
)
+
1
2
l
¨
(
y
i
,
y
i
^
t
−
1
)
f
t
(
x
i
)
2
)
+
γ
T
+
∑
j
=
1
T
λ
w
j
2
+
C
令
g
i
=
l
˙
(
y
i
,
y
i
^
t
−
1
)
,
h
i
=
l
¨
(
y
i
,
y
i
^
t
−
1
)
,
对
于
第
t
棵
树
l
(
y
i
,
y
i
^
t
−
1
)
已
知
,
则
变
成
L=\sum_{i=1}^ml(y_i,\hat{y_i})+\Omega(f_t)+C\\ =\sum_{i=1}^ml(y_i,\hat{y_i}^{t-1}+f_t(x_i))+\gamma T+\sum_{j=1}^T\lambda w_j^2+C,解释\hat{y_i}^{t-1}为前面t-1个学习器的预测值\\ 由泰勒展开f(x+\Delta x)=f(x)+\dot{f}(x)\Delta x+\frac{1}{2}\ddot{f}(x)\Delta x^2\\ L=\sum_{i=1}^m(l(y_i,\hat{y_i}^{t-1})+\dot{l}(y_i,\hat{y_i}^{t-1})f_t(x_i)+\frac{1}{2}\ddot{l}(y_i,\hat{y_i}^{t-1})f_t(x_i)^2)+\gamma T+\sum_{j=1}^T\lambda w_j^2+C\\ 令g_i=\dot{l}(y_i,\hat{y_i}^{t-1}),h_i=\ddot{l}(y_i,\hat{y_i}^{t-1}),对于第t棵树l(y_i,\hat{y_i}^{t-1})已知,则变成
L=i=1∑ml(yi,yi^)+Ω(ft)+C=i=1∑ml(yi,yi^t−1+ft(xi))+γT+j=1∑Tλwj2+C,解释yi^t−1为前面t−1个学习器的预测值由泰勒展开f(x+Δx)=f(x)+f˙(x)Δx+21f¨(x)Δx2L=i=1∑m(l(yi,yi^t−1)+l˙(yi,yi^t−1)ft(xi)+21l¨(yi,yi^t−1)ft(xi)2)+γT+j=1∑Tλwj2+C令gi=l˙(yi,yi^t−1),hi=l¨(yi,yi^t−1),对于第t棵树l(yi,yi^t−1)已知,则变成
L = ∑ i = 1 m ( g i f t ( x i ) + 1 2 h i f t ( x i ) 2 ) + γ T + ∑ j = 1 T λ w j 2 + C 1. L=\sum_{i=1}^m(g_if_t(x_i)+\frac{1}{2}h_if_t(x_i)^2)+\gamma T+\sum_{j=1}^T\lambda w_j^2+C1. L=i=1∑m(gift(xi)+21hift(xi)2)+γT+j=1∑Tλwj2+C1.
对于第t棵树的函数
f
t
(
x
)
f_t(x)
ft(x),可以认为是
f
t
(
x
)
=
w
q
(
x
)
,
其
中
q
(
x
)
=
1
,
2
,
⋯
,
T
f_t(x)=w_{q(x)},其中q(x)=1,2,\cdots,T
ft(x)=wq(x),其中q(x)=1,2,⋯,T,这个可以理解,上述式子就变成
L
=
∑
i
=
1
m
(
g
i
w
q
(
x
)
+
1
2
h
i
w
q
(
x
)
2
)
+
γ
T
+
∑
j
=
1
T
λ
w
j
2
+
C
1.
(
1
)
L=\sum_{i=1}^m(g_iw_{q(x)}+\frac{1}{2}h_iw_{q(x)}^2)+\gamma T+\sum_{j=1}^T\lambda w_j^2+C1.(1)
L=i=1∑m(giwq(x)+21hiwq(x)2)+γT+j=1∑Tλwj2+C1.(1)
进一步变形为
L
=
∑
j
=
1
T
(
(
∑
x
i
∈
R
j
g
i
)
w
j
+
1
2
(
∑
x
i
∈
R
j
h
i
)
w
j
2
)
+
γ
T
+
∑
j
=
1
T
λ
w
j
2
+
C
1.
(
2
)
解
释
R
j
为
第
j
个
叶
子
节
点
的
区
域
L=\sum_{j=1}^T((\sum_{x_i\in R_j}g_i)w_j+\frac{1}{2}(\sum_{x_i\in R_j}h_i)w_j^2) +\gamma T+\sum_{j=1}^T\lambda w_j^2+C1.(2)\\ 解释R_j为第j个叶子节点的区域
L=j=1∑T((xi∈Rj∑gi)wj+21(xi∈Rj∑hi)wj2)+γT+j=1∑Tλwj2+C1.(2)解释Rj为第j个叶子节点的区域
式子(1)是对于样本遍历,将每个样本的
g
i
,
h
i
g_i,h_i
gi,hi及其所属的区域的评分
w
q
(
x
)
w_{q(x)}
wq(x)取函数
式子(2)是对于叶子节点遍历,将每个叶子节点上的样本的 g , h g,h g,h及其该节点的评分 w j w_j wj取函数,与(1)是等价的
进一步变形
L
=
∑
j
=
1
T
(
(
∑
x
i
∈
R
j
g
i
)
w
j
+
1
2
(
∑
x
i
∈
R
j
h
i
+
λ
)
w
j
2
)
+
γ
T
+
C
1.
L=\sum_{j=1}^T((\sum_{x_i\in R_j}g_i)w_j+\frac{1}{2}(\sum_{x_i\in R_j}h_i+\lambda )w_j^2) +\gamma T+C1.
L=j=1∑T((xi∈Rj∑gi)wj+21(xi∈Rj∑hi+λ)wj2)+γT+C1.
要想使得
L
L
L最小,则
L
L
L对
w
j
w_j
wj求导并等于0,得
令
G
j
=
∑
x
i
∈
R
j
g
i
,
H
j
=
∑
x
i
∈
R
j
h
i
G_j=\sum_{x_i\in R_j}g_i,H_j=\sum_{x_i\in R_j}h_i
Gj=∑xi∈Rjgi,Hj=∑xi∈Rjhi,有
∂
L
∂
w
j
=
G
j
+
(
H
j
+
λ
)
w
j
=
0
w
j
=
−
G
j
H
j
+
λ
.
\frac{\partial L}{\partial w_j}=G_j+(H_j+\lambda)w_j=0\\ w_j=-\frac{G_j}{H_j+\lambda}.\\
∂wj∂L=Gj+(Hj+λ)wj=0wj=−Hj+λGj.
此时目标函数即损失函数为(将
w
j
w_j
wj代入原式)
L
=
−
1
2
∑
j
=
1
T
G
j
2
H
j
+
λ
+
γ
T
L=-\frac{1}{2}\sum_{j=1}^T\frac{G_j^2}{H_j+\lambda}+\gamma T
L=−21j=1∑THj+λGj2+γT
我们便可以根据这个最终版本的损失函数来对树进行分支,即对每个可以分支的特征算出上述损失函数的值,求
Δ
L
=
1
2
[
G
L
2
H
L
+
λ
+
G
R
2
H
R
+
λ
−
(
G
L
+
G
R
)
2
H
L
+
H
R
+
λ
]
−
λ
\Delta L=\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}]-\lambda
ΔL=21[HL+λGL2+HR+λGR2−HL+HR+λ(GL+GR)2]−λ
上述式子可以理解为树的节点不分裂的损失函数减去二分后左子树的损失函数和右子树的损失函数,因为多了一个节点,所有再减去
λ
\lambda
λ,这个值越小,说明分支越好。有个疑问为什么越小越好
综上就是XGBoost算法,基本而已。
对于XGBoost更加强大的地方,也是其更加多的使用在比赛或者实际当中,就是XGBoost的运行速度是GDBT的10倍,因为其能够进行大量的并行度的运算,当然,这个并行度不是树与树之间的,因为boositng终究是串行的,一颗树的生成需要前一棵树的数据,这个并行是指树内特征间的并行,也就是如何生成一颗树的速度大大提高,这也是GBDT最耗时的地方
对于更加完整的XGBoost模型,还加载了许许多多很牛逼厉害的东西,比如对缺失值的处理,对内存的优化(还考虑到了cache的命中率)等
详见XGBoost原论文