GBDT原理及实现(XGBoost+LightGBM)
一、准备知识
1.1 泰勒展开
1.1.1 基本定理
函数
f
(
x
)
f(x)
f(x) 在点
x
0
x_0
x0 的邻域内从1到
n
+
1
n+1
n+1阶可导,则
f
(
x
)
f(x)
f(x)可展开为:
f
(
x
)
=
f
(
x
0
)
+
f
′
(
x
0
)
(
x
−
x
0
)
+
1
2
!
f
′
′
(
x
0
)
(
x
−
x
0
)
2
+
⋯
+
1
n
!
f
(
n
)
(
x
0
)
(
x
−
x
0
)
n
+
1
(
n
+
1
)
!
f
(
n
)
(
ξ
)
(
x
−
x
0
)
(
n
+
1
)
f(x)=f(x_0)+f'(x_0)(x-x_0)+\frac{1}{2!}f''(x_0)(x-x_0)^2+\cdots\\ +\frac{1}{n!}f^{(n)}(x_0)(x-x_0)^n+\frac{1}{(n+1)!}f^{(n)}(\xi)(x-x_0)^{(n+1)}
f(x)=f(x0)+f′(x0)(x−x0)+2!1f′′(x0)(x−x0)2+⋯+n!1f(n)(x0)(x−x0)n+(n+1)!1f(n)(ξ)(x−x0)(n+1)
也可以简写成如下形式:
f
(
x
)
=
∑
n
=
0
∞
1
n
!
f
(
x
0
)
(
x
−
x
0
)
n
f(x)=\sum_{n=0}^\infty \frac{1}{n!}f(x_0)(x-x_0)^n
f(x)=n=0∑∞n!1f(x0)(x−x0)n
1.1.2 常用展开
设 x 1 = x 0 + Δ x x_1=x_0+\Delta x x1=x0+Δx,则有一阶和二阶两种常用展开,前者只用到一阶倒数,后者还要求函数 f f f 二阶可导。
- 一阶泰勒展开
f ( x 1 ) ≈ f ( x 0 ) + f ′ ( x 0 ) Δ x f(x_1)\approx f(x_0)+f'(x_0)\Delta x f(x1)≈f(x0)+f′(x0)Δx - 二阶泰勒展开
f ( x 1 ) ≈ f ( x 0 ) + f ′ ( x 0 ) Δ x + 1 2 f ′ ′ ( x 0 ) Δ x 2 f(x_1)\approx f(x_0)+f'(x_0)\Delta x+\frac{1}{2}f''(x_0)\Delta x^2 f(x1)≈f(x0)+f′(x0)Δx+21f′′(x0)Δx2
举个例子,在迭代算法中,往往有
x
t
+
1
=
x
t
+
v
x_{t+1} = x_t + v
xt+1=xt+v,将
f
(
x
t
+
1
)
f(x_{t+1})
f(xt+1) 在
x
t
x_t
xt 附近展开(一阶):
f
(
x
t
+
1
)
=
f
(
x
t
+
v
)
≈
f
(
x
t
)
+
f
′
(
x
t
)
⋅
v
f(x_{t+1})=f( x_t + v)\approx f(x_t)+f'(x_t)\cdot v
f(xt+1)=f(xt+v)≈f(xt)+f′(xt)⋅v
1.1.3 小知识:如何用泰勒展开解释 “为什么负梯度是下降最快的方向?”
假设当前点是
x
x
x,我们想要找到使得
f
(
x
)
f(x)
f(x) 下降最快的方向,即找到:
arg
max
v
f
(
x
)
−
f
(
x
+
v
)
\arg \max_v f(x)-f(x+v)
argvmaxf(x)−f(x+v)
将
f
(
x
+
v
)
f(x+v)
f(x+v) 在
x
x
x 附近展开得到:
f
(
x
+
v
)
=
f
(
x
)
+
g
t
⋅
v
f
(
x
)
−
f
(
x
+
v
)
=
(
−
g
t
)
⋅
v
f(x+v) = f(x)+g_t\cdot v\\ f(x)-f(x+v)=(-g_t)\cdot v
f(x+v)=f(x)+gt⋅vf(x)−f(x+v)=(−gt)⋅v
等式右边是两个向量做乘法,他们在平行的时候,点积最大,因此
v
=
−
g
t
v=-g_t
v=−gt 是下降最快的方向。
1.2 梯度下降法
1.2.1 基本介绍
梯度下降法,或最速下降法,属于利用一阶导数的无约束目标最优化方法。基本思想是,在每一次迭代中,使用负梯度方向为搜索(更新)方向。
GBDT是利用梯度下降法进行优化的,它在每一次迭代拟合当前模型的负梯度。
- 算法
假设无约束最优化问题是:
min x f ( x ) \min_x f(x) xminf(x)
则在每一次迭代以当前 x ( t ) x^{(t)} x(t) 的负梯度为搜索方向, λ t \lambda_t λt 为步长更新 x ( t ) x^{(t)} x(t):
x ( t + 1 ) = x ( t ) − λ t ⋅ f ′ ( x ( t ) ) x^{(t+1)}=x^{(t)}-\lambda_t \cdot f'(x^{(t)}) x(t+1)=x(t)−λt⋅f′(x(t))
其中步长 λ t \lambda_t λt 可以通过一维搜索确定:
λ t = a r g min λ f ( x ( t + 1 ) ) \lambda_t=arg\min_{\lambda}f(x^{(t+1)}) λt=argλminf(x(t+1))
1.3 牛顿法
1.3.1 基本介绍
牛顿法属于利用一阶导数和二阶导数的无约束目标最优化方法。基本思想是,在每一次迭代中,以牛顿方向(一阶与二阶之比取负)为搜索方向进行更新。牛顿法对目标的可导性更严格,要求二阶可导,有Hesse矩阵求逆计算复杂的缺点。
XGBoost是利用牛顿法进行优化的。
关于牛顿法和拟牛顿法的详细介绍可以看这里。
1.3.2基本原理
假设无约束最优化问题是
min
x
f
(
x
)
\min_x f(x)
xminf(x)
对于一维
x
x
x (标量),将
f
(
x
)
f(x)
f(x) 在当前迭代点
x
(
t
)
x^{(t)}
x(t) 附近用二阶泰勒展开:
f
(
x
(
t
+
1
)
)
=
f
(
x
(
t
)
)
+
f
′
(
x
(
t
)
)
Δ
x
+
1
2
f
′
′
(
x
(
t
)
)
Δ
x
2
f(x^{(t+1)})=f(x^{(t)})+f'(x^{(t)})\Delta x+\frac{1}{2}f''(x^{(t)})\Delta x^2
f(x(t+1))=f(x(t))+f′(x(t))Δx+21f′′(x(t))Δx2
用泰勒展开的极值点近似
f
(
x
)
f(x)
f(x)的极值点:
∂
f
(
x
(
t
+
1
)
)
∂
Δ
x
=
f
′
(
x
(
t
)
)
+
f
′
′
(
x
(
t
)
)
Δ
x
=
0
\frac{\partial f(x^{(t+1)})}{\partial \Delta x}=f'(x^{(t)})+f''(x^{(t)})\Delta x=0
∂Δx∂f(x(t+1))=f′(x(t))+f′′(x(t))Δx=0
因此:
Δ
x
=
x
(
t
+
1
)
−
x
(
t
)
=
−
f
′
(
x
(
t
)
)
f
′
′
(
x
(
t
)
)
\Delta x = x^{(t+1)}-x^{(t)}=-\frac{f'(x^{(t)})}{f''(x^{(t)})}
Δx=x(t+1)−x(t)=−f′′(x(t))f′(x(t))
于是得到迭代公式,
g
t
g_t
gt 和
h
t
h_t
ht 分别是目标的一阶和二阶导在
x
(
t
)
x^{(t)}
x(t) 上的取值
x
(
t
+
1
)
=
x
(
t
)
−
g
t
h
t
x^{(t+1)}=x^{(t)}-\frac{g_t}{h_t}
x(t+1)=x(t)−htgt
推广到
x
x
x 是多维向量的情况,设
H
H
H 是Hesse矩阵
x
(
t
+
1
)
=
x
(
t
)
−
H
t
−
1
g
t
x^{(t+1)}=x^{(t)}-H_t^{-1}g_t
x(t+1)=x(t)−Ht−1gt
可见每一次迭代都需要计算矩阵的逆。
- 算法
每一次迭代时,计算Hesse矩阵和一阶导数 g g g
H ( x ) = [ ∂ 2 f ∂ x i ∂ x j ] H(x)=\left [ \frac{\partial^2f}{\partial x_i\partial x_j} \right ] H(x)=[∂xi∂xj∂2f]
利用上面的迭代公式进行更新。
1.4 CART树
CART(classification and regression tree)树是决策树的一种,既可以实现分类也可以实现回归,正是它命名的由来。它规定树的结构是二叉树,每个结点上的分叉条件形似 “ I D = s ID=s ID=s ?” 或者 “ A < a A<a A<a ?”。特征选择策略为,分类树 采用基尼指数最小化准则,回归树 采用平方误差最小化准则。
1.4.1 CART回归树
CART回归树的构建是一个递归的过程。CART回归树的每个结点(包括中间结点和根)都有一个输出,他等于结点中所有样本的输出平均值。对于一棵训练好的CART回归树,总能将待测样本分到某个叶子结点上,模型关于该样本的输出,正是该叶子结点输出的权值。
A. 单元最优输出
CART回归树总是对应着输入特征空间的一个划分,以及在划分的单元上的输出。假设CART将输入空间划分为
M
M
M 个单元
R
m
R_m
Rm(对应于
M
M
M个叶子结点),各单元的输出为
c
m
c_m
cm,则CART模型可以表示为:
f
(
x
)
=
∑
m
=
1
M
c
m
I
(
x
∈
R
m
)
f(x)=\sum_{m=1}^Mc_mI(x\in R_m)
f(x)=m=1∑McmI(x∈Rm)
以最小化平方误差
∑
x
i
∈
R
m
(
y
i
−
f
(
x
i
)
)
2
\sum_{x_i\in R_m}(y_i-f(x_i))^2
∑xi∈Rm(yi−f(xi))2 为目标,容易看出,单元
R
m
R_m
Rm(叶子结点
m
m
m)上的输出权值
c
m
c_m
cm 的最优值应是
R
m
R_m
Rm 上的样本的输出(指
y
i
y_i
yi)的均值:
c
m
∗
=
a
v
g
(
y
i
∣
x
i
∈
R
m
)
c_m^*=avg(y_i|x_i\in R_m)
cm∗=avg(yi∣xi∈Rm)
B. 分裂策略
为了求各单元最优输出,首先要确定如何划分(分裂)。CART回归树以最小化平方误差为分裂依据。对每个特征
x
(
j
)
x^{(j)}
x(j),找到一个最优的划分点
s
(
j
)
s^{(j)}
s(j) 将样本划分成两部分
R
1
R_1
R1 和
R
2
R_2
R2,然后选取最优划分点最优的特征作为最优特征,相应的划分点作为最优划分点。
min
j
,
s
{
min
c
1
∑
x
i
∈
R
1
(
y
i
−
c
1
)
2
+
min
c
2
∑
x
i
∈
R
2
(
y
i
−
c
2
)
2
}
\min_{j,s}\left\{\min_{c_1}\sum_{x_i\in R_1}(y_i-c_1)^2+\min_{c_2}\sum_{x_i\in R_2}(y_i-c_2)^2\right\}
j,smin{c1minxi∈R1∑(yi−c1)2+c2minxi∈R2∑(yi−c2)2}
其中各区域的最佳输出是:
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)
从目标上看,该策略不断尝试将当前结点的样本根据某个特征的取值分成两部分,选取拟合效果最佳的方案(最佳特征 + 最佳特征的最佳分裂点)。
下面举例说明CART回归树单特征的最佳分裂点选择
假设有四个样本,一维特征是
A
A
A,它的取值和对应的label如下。每两个取值之间,都能选为一个分界面(例如0.1和0.2之间选0.15为分界面),列举出三种划分情况,分别计算他们的平方误差。
对于
D
1
D_1
D1,
c
1
=
0
c_1=0
c1=0,
c
1
=
(
0
+
1
+
1
)
/
3
=
0.67
c_1=(0+1+1)/3=0.67
c1=(0+1+1)/3=0.67
l
o
s
s
1
=
∑
i
=
1
1
(
y
i
−
c
1
)
2
+
∑
i
=
1
3
(
y
i
−
c
2
)
2
=
(
0
−
0
)
2
+
(
0
−
0.67
)
2
+
(
1
−
0.67
)
2
+
(
1
−
0.67
)
2
=
0.67
loss_1=\sum_{i=1}^1(y_i-c_1)^2+\sum_{i=1}^3(y_i-c_2)^2\\ =(0-0)^2+(0-0.67)^2+(1-0.67)^2+(1-0.67)^2=0.67
loss1=i=1∑1(yi−c1)2+i=1∑3(yi−c2)2=(0−0)2+(0−0.67)2+(1−0.67)2+(1−0.67)2=0.67
同理对于
D
2
D_2
D2、
D
3
D_3
D3计算得到:
l
o
s
s
2
=
0
l
o
s
s
3
=
0.67
loss_2 = 0\\loss_3=0.67
loss2=0loss3=0.67
显然
D
2
D_2
D2这个划分(
R
1
=
{
0.1
,
0.2
}
R_1=\left\{0.1,0.2\right\}
R1={0.1,0.2},
R
2
=
{
0.3
,
0.4
}
R_2=\left\{0.3,0.4\right\}
R2={0.3,0.4},最佳分裂点 0.25)是特征
A
A
A 的最佳分裂。
C. CART回归树生成步骤
-
遍历特征 x ( j ) x^{(j)} x(j),固定特征 x ( j ) x^{(j)} x(j)遍历切分点 s ( j ) s^{(j)} s(j)(一般对样本在 x ( j ) x^{(j)} x(j)排序,然后每两个样本取均值得到),求解:
min j , s { min c 1 ∑ x i ∈ R 1 ( y i − c 1 ) 2 + min c 2 ∑ x i ∈ R 2 ( y i − c 2 ) 2 } \min_{j,s}\left\{\min_{c_1}\sum_{x_i\in R_1}(y_i-c_1)^2+\min_{c_2}\sum_{x_i\in R_2}(y_i-c_2)^2\right\} j,smin{c1minxi∈R1∑(yi−c1)2+c2minxi∈R2∑(yi−c2)2} -
用选定的最优特征 x ( j ) x^{(j)} x(j)和切分点 s ( j ) s^{(j)} s(j)划分样本空间,计算两个子结点的输出值
R 1 = { x ∣ x i ( j ) ⩽ s ( j ) } , R 2 = { x ∣ x i ( j ) > s ( j ) } R_1=\left\{x|x_i^{(j)}\leqslant s^{(j)}\right\},R_2=\left\{x|x_i^{(j)}>s^{(j)}\right\} R1={x∣xi(j)⩽s(j)},R2={x∣xi(j)>s(j)}
c ^ 1 = 1 ∣ R 1 ∣ ∑ x i ∈ R 1 y i c ^ 2 = 1 ∣ R 2 ∣ ∑ x i ∈ R 2 y i \hat{c}_1=\frac{1}{|R_1|}\sum_{x_i \in R_1}y_i\\ \hat{c}_2=\frac{1}{|R_2|}\sum_{x_i \in R_2}y_i c^1=∣R1∣1xi∈R1∑yic^2=∣R2∣1xi∈R2∑yi
递归对两个子空间进行划分,连续特征可重复选用,直到满足限制或者不能再划分为止。 -
最终回归树CART
f ( x ) = ∑ m = 1 M c ^ m I ( x ∈ R m ) f(x)=\sum_{m=1}^M\hat{c}_mI(x\in R_m) f(x)=m=1∑Mc^mI(x∈Rm)
来一个待测 x x x,它会经历CART树各层判断,到达某个叶子结点,模型将输出该叶子结点的 c ^ m \hat{c}_m c^m。
1.4.2 CART分类树
A. 基尼指数
概率分布的基尼指数【定义】:
G
i
n
i
(
p
)
=
∑
k
=
1
K
p
k
(
1
−
p
k
)
=
1
−
∑
k
p
k
2
Gini(p)=\sum_{k=1}^K p_k (1-p_k)=1-\sum_k p_k^2
Gini(p)=k=1∑Kpk(1−pk)=1−k∑pk2
特别地,对于二分类,概率分布的基尼指数:
G
i
n
i
(
p
)
=
2
p
(
1
−
p
)
Gini(p)=2p(1-p)
Gini(p)=2p(1−p)
对于数据集
D
D
D,定义基尼指数:
G
i
n
i
(
D
)
=
1
−
∑
k
(
∣
C
k
∣
∣
D
∣
)
2
Gini(D)=1-\sum_k(\frac{|C_k|}{|D|})^2
Gini(D)=1−k∑(∣D∣∣Ck∣)2
当数据集
D
D
D按照特征取值
A
=
a
A=a
A=a 分为两部分时(
A
=
a
A=a
A=a对应
D
1
D_1
D1,
A
≠
a
A\neq a
A̸=a对应
D
2
D_2
D2):
G
i
n
i
(
D
,
A
)
=
∣
D
1
∣
∣
D
∣
G
i
n
i
(
D
1
)
+
∣
D
2
∣
∣
D
∣
G
i
n
i
(
D
2
)
Gini(D,A)=\frac{|D_1|}{|D|}Gini(D_1)+\frac{|D_2|}{|D|}Gini(D_2)
Gini(D,A)=∣D∣∣D1∣Gini(D1)+∣D∣∣D2∣Gini(D2)
其中特征
A
A
A 的每个取值的基尼系数
G
i
n
i
(
D
i
)
Gini(D_i)
Gini(Di):
G
i
n
i
(
D
i
)
=
1
−
∑
k
(
∣
C
i
k
∣
∣
D
i
∣
)
2
Gini(D_i)=1-\sum_k(\frac{|C_{ik}|}{|D_i|})^2
Gini(Di)=1−k∑(∣Di∣∣Cik∣)2
D
i
D_i
Di是特征
A
A
A取值为
a
i
a_i
ai的样本,
C
i
k
C_{ik}
Cik是
D
i
D_i
Di里类别为
k
k
k的样本。
【基尼指数的意义】
个人理解,
G
i
n
i
(
D
)
Gini(D)
Gini(D) 描述了集合
D
D
D 的不确定性(这点和熵有点像),而
G
i
n
i
(
D
,
A
)
Gini(D,A)
Gini(D,A) 描述了经过
A
=
a
A=a
A=a 的判定分割后,集合
D
D
D 仍存在的不确定性。
【基尼指数越小越好】
- 对一个特征
A
A
A 而言,用基尼指数小的取值作最优切分点。
基尼指数在等概分布时最大,若在 A A A 的每一种取值里,样本取不同类别的概率都相等,则基尼指数大,划分效果差(划分后没有改善不确定性,这点与熵类似)。若在 A A A 的每一种取值里,样本都属于同类别(例如 A = a A=a A=a 时label全是1, A ≠ a A\neq a A̸=a 时label全是0 ),基尼指数小,划分效果好(用特征 A A A和分裂点 a a a划分后已经能直接区分)。 - 对不同特征 A 1 , A 2 , ⋯ A_1,A_2,\cdots A1,A2,⋯ 而言,基尼指数小的特征更优。
B. CART分类树生成步骤
-
假设分到当前结点的样本集为 D D D 。遍历特征 x ( j ) x^{(j)} x(j),固定特征 x ( j ) x^{(j)} x(j) 遍历取值 s ( j ) s^{(j)} s(j),按照是否有 x ( j ) = s ( j ) x^{(j)}=s^{(j)} x(j)=s(j) 把 D D D 分成 D 1 D_1 D1 和 D 2 D_2 D2,分别计算每个特征每个取值的基尼系数 G i n i ( D i ) Gini(D_i) Gini(Di),用来计算特征 x ( j ) x^{(j)} x(j) 的基尼系数 G i n i ( D , x ( j ) ) Gini(D,x^{(j)}) Gini(D,x(j))。
-
选择基尼系数 G i n i ( D , x ( j ) ) Gini(D,x^{(j)}) Gini(D,x(j)) 最小的特征,以及对应取值 s ( j ) s^{(j)} s(j) 作为最优特征和切分点,划分样本 D D D。
-
递归对每个样本子集进行划分。
1.5 Boosting
1.5.1 简介
Boosting属于集成学习(Ensemble)的一种,是一种将一系列弱学习器提升为一个强学习器的方法,工作机制基本上是每次迭代从训练集训练出一个基学习器,然后根据本次迭代基学习器的性能,调整训练集样本的分布,或者改变拟合的目标,使得后续的基学习器更多地去关注之前的基学习器判断错误的样本。最终,学习器之间的组合采用加法模型,即基函数的加权线性组合。
常用的Boosting算法包括Adaboost、提升树、gbdt等等。
Boosting算法要求基学习器能对特定的数据分布进行学习,从偏差-方差(bias-variance)的角度看,Boosting更关注降低偏差,因此Boosting能基于泛化能力很弱的基学习器构造出很强的集成模型。
1.6 CSC
1.6.1 Compressed Sparse Column (CSC)
将矩阵按列存储的稀疏格式。包含四个部分(向量):
1. data 数据
2. indices 指示数据各列非零元素的位置
3. indprt 用于分割 indices
4. size 表示矩阵大小
1.6.2 具体举例
[ 1 0 0 0 3 0 2 0 4 ] \left [\begin{matrix} 1 & 0 & 0\\ 0 & 3 & 0\\ 2 & 0 & 4 \end{matrix}\right ] ⎣⎡102030004⎦⎤
利用CSC得到的压缩矩阵的各组成部分:
1. data = [1,2,3,4]
2. indices = [0,2,1,2]
3. indptr = [0,2,3,4]
4. size = [3,3]
矩阵的第一列非零元素下标为0和2,第二列为1,第三列为2,因此indices如上。由于indices是向量形式,用indptr将其按列划分,它表示indices第0到第1个元素表示第一列,第2个元素表示第二列,第3个元素表示第三列。从例子似乎看不出稀疏表示的优越性,实际上当各列足够稀疏(例如上万行只有几个非零元素)时才能显出。
二、GBDT
2.1 提升树
提升树以决策树为基函数的Boosting模型(基函数系数可以固定为1):
f
(
x
)
=
∑
m
=
1
M
T
(
x
;
θ
m
)
f(x)=\sum_{m=1}^MT(x;\theta_m)
f(x)=m=1∑MT(x;θm)
以下为 提升回归树算法:
- 初始化 f 0 ( x ) = 0 f_0(x)=0 f0(x)=0
- 进行
M
M
M 轮训练。
每一轮用上一轮的模型为每个样本 x i x_i xi 进行预测,和真实结果求残差
r m i = y i − f m − 1 ( x i ) , i = 1 , 2 , ⋯   , N \begin{matrix} r_{mi}=y_i-f_{m-1}(x_i), &i=1,2,\cdots,N \end{matrix} rmi=yi−fm−1(xi),i=1,2,⋯,N
以拟合残差为目标训练一棵树,得到 T ( x ; θ m ) T(x;\theta_m) T(x;θm),并更新模型
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) - 用最后一个模型作为最终模型
f ( x ) = f M ( x ) = ∑ i T ( x ; θ m ) f(x)=f_M(x)=\sum_iT(x;\theta_m) f(x)=fM(x)=i∑T(x;θm)
下面用一个只有一维特征的例子举例说明如何训练 提升回归树
|
x
i
x_i
xi | 1 | 2 | 3 | 4 | 5 | 6 |
| – |:–?:–?:–?:–?:–?
|
y
i
y_i
yi | 10 | 20 | 30 | 40 | 50 | 60 |
原表正是第一轮要拟合的目标,利用 CART 回归树的分裂方法计算每个分裂点下的均方误差:
s s s | 1.5 | 2.5 | 3.5 | 4.5 | 5.5 |
---|---|---|---|---|---|
M S E ( s ) MSE(s) MSE(s) | 1000 | 550 | 400 | 550 | 1000 |
所以本轮选择 3.5 作为分裂点,第一轮的树表示为:
f
1
(
x
)
=
T
1
(
x
)
=
{
20
,
x
⩽
3.5
50
,
x
>
3.5
f_1(x)=T_1(x)=\left \{ \begin{matrix} 20,& x\leqslant 3.5 \\50,& x> 3.5\end{matrix}\right .
f1(x)=T1(x)={20,50,x⩽3.5x>3.5
计算本轮残差,作为下一轮要拟合的目标
|
x
i
x_i
xi | 1 | 2 | 3 | 4 | 5 | 6 |
| – |:–?:–?:–?:–?:–?
|
y
i
y_i
yi | -10 | 0 | 10 | -10 | 0 | 10 |
与第一轮类似地,计算每个分裂点下的均方误差:
s s s | 1.5 | 2.5 | 3.5 | 4.5 | 5.5 |
---|---|---|---|---|---|
M S E ( s ) MSE(s) MSE(s) | 280 | 325 | 400 | 325 | 280 |
所以第二轮选择 1.5 作为分裂点,并与第一轮综合起来
T
2
(
x
)
=
{
−
10
,
x
⩽
1.5
2
,
x
>
1.5
T_2(x)=\left \{ \begin{matrix} -10,& x\leqslant 1.5 \\2,& x> 1.5\end{matrix}\right .
T2(x)={−10,2,x⩽1.5x>1.5
f
2
(
x
)
=
T
1
(
x
)
+
T
2
(
x
)
=
{
20
−
10
=
10
,
x
⩽
1.5
20
+
2
=
22
,
1.5
<
x
⩽
3.5
50
+
2
=
52
,
x
>
3.5
f_2(x)=T_1(x)+T_2(x)=\left \{ \begin{matrix} 20-10=10, & x\leqslant 1.5\\ 20+2=22, & 1.5<x\leqslant 3.5\\ 50 + 2=52, & x>3.5 \end{matrix} \right .
f2(x)=T1(x)+T2(x)=⎩⎨⎧20−10=10,20+2=22,50+2=52,x⩽1.51.5<x⩽3.5x>3.5
计算本轮残差,作为下一轮要拟合的目标
|
x
i
x_i
xi | 1 | 2 | 3 | 4 | 5 | 6 |
| – |:–?:–?:–?:–?:–?
|
y
i
y_i
yi | 0 | -2 | 8 | -12 | 2 | 8 |
经过这一轮,可以看到
x
1
x_1
x1 和
x
2
x_2
x2 的残差其实已经很小了,如此继续下去迭代若干次得到的叠加模型,就是最终的提升树模型。
2.2 梯度提升树GBDT
当损失函数是平方损失时,每一轮计算残差是简单的,对于一般的损失函数可能不是那么友好(比如Huber损失),Freidman大神提出梯度提升树算法,用损失函数关于上一轮模型输出的负梯度近似残差,每一轮去拟合这个残差。其他方面与普通的提升树无异。
r
m
i
=
−
[
∂
l
(
y
i
,
f
(
x
i
)
)
∂
f
(
x
i
)
]
f
(
x
)
=
f
m
−
1
(
x
)
r_{mi}=-\left [ \frac{\partial l(y_i,f(x_i))}{\partial f(x_i)}\right]_{f(x)=f_{m-1}(x)}
rmi=−[∂f(xi)∂l(yi,f(xi))]f(x)=fm−1(x)
小问题1:为什么GBDT要拟合负梯度呢?
负梯度是loss下降最快的方向,每一个基函数去拟合负梯度,最终的叠加也是loss下降最快的方向。普通的提升树之所以拟合残差,实际上是因为它使用平方误差,其梯度正式残差,因此可以将残差理解为负梯度在loss函数使用平方误差时的特例。使用负梯度作为拟合目标的好处在于,能更快地收敛,以及更具有普适性,即适用于更多的loss形式,而不拘泥与平方误差。
小问题2:GBDT与RF各有什么优缺点?
首先是树模型所具备的一些共有的优点
- 实现比较简单
- 能训练高维数据
- 对稀疏特征比较友好,即使有缺失值也能进行学习
- 能进行特征筛选(通过给出特征重要性)
GBDT的优点
- 即使每一棵树泛化能力极差,最终组合的模型也能很强
- 每一轮拟合负梯度,收敛快
GBDT的缺点
- 基函数之间有串行依赖关系,无法做树维度的并行
- 容易过拟合(没有正则,没有子采样,只有剪枝)
RF的优点
- 有特征子采样,有利于降低过拟合
- 基函数之间没有依赖关系,容易做并行
RF的缺点
- 可能有很多相同或者相似度很高的重复基函数
2.3 XGBoost
2.3.1 模型形式
回归树
回归树的每个叶子结点都有其对应的分数(score)
w
j
w_j
wj,在回归问题中,
w
j
w_j
wj直接作为预测结果输出,在分类任务中则用sigmoid转换为概率。样本
x
x
x经过回归树必被分到某个叶子上,该叶子的输出
w
j
w_j
wj即回归树的输出。
因此,若定义
q
(
x
)
q(x)
q(x)为取叶结点下标函数,则回归树可以表示为:
f
k
(
x
i
)
=
w
q
(
x
i
)
f_k(x_i)=w_{q(x_i)}
fk(xi)=wq(xi)
另外,定义集合
I
j
=
{
i
∣
q
(
x
i
)
=
j
}
I_j=\left \{ i|q(x_i)=j\right \}
Ij={i∣q(xi)=j} 表示被
f
k
f_k
fk划分到第
j
j
j个叶结点上的样本的下标集。
XGBoost定义的树模型
给定数据集
D
=
{
(
x
1
,
y
1
)
,
⋯
 
,
(
x
n
,
y
n
)
}
D=\left\{(x_1,y_1),\cdots,(x_n,y_n)\right\}
D={(x1,y1),⋯,(xn,yn)},XGBoost定义模型为
K
K
K棵回归树的加法模型:
y
^
i
=
f
(
x
i
)
=
∑
k
=
1
K
α
k
f
k
(
x
i
)
\hat{y}_i=f(x_i)=\sum_{k=1}^K\alpha_k f_k(x_i)
y^i=f(xi)=k=1∑Kαkfk(xi)
2.3.2 目标函数
XGBoost的目标函数
XGBoost将目标定义为目标损失与正则项之和,
l
l
l是衡量样本总体的拟合情况的损失函数,
Ω
\Omega
Ω衡量树的复杂度
O
b
j
(
θ
)
=
L
(
θ
)
+
Ω
(
θ
)
=
∑
i
=
1
n
l
(
y
i
,
y
^
i
)
+
∑
k
=
1
K
Ω
(
f
k
)
Obj(\theta)=L(\theta)+\Omega(\theta)\\ =\sum_{i=1}^nl(y_i,\hat{y}_i)+\sum_{k=1}^K\Omega(f_k)
Obj(θ)=L(θ)+Ω(θ)=i=1∑nl(yi,y^i)+k=1∑KΩ(fk)
其中损失函数可以是均方差或逻辑loss
l
(
y
i
,
y
^
i
)
=
1
2
l
(
y
i
−
y
^
i
)
2
l(y_i,\hat{y}_i)=\frac{1}{2}l(y_i-\hat{y}_i)^2
l(yi,y^i)=21l(yi−y^i)2
l
(
y
i
,
y
^
i
)
=
y
i
log
(
1
+
e
−
y
^
i
)
+
(
1
−
y
i
)
log
(
1
+
e
y
^
i
)
l(y_i,\hat{y}_i)=y_i\log(1+e^{-\hat{y}_i})+(1-y_i)\log(1+e^{\hat{y}_i})
l(yi,y^i)=yilog(1+e−y^i)+(1−yi)log(1+ey^i)
正则项可以是L1正则(LASSO)或L2正则(岭回归)
正则项
从目标函数可以看出,XGBoost对每棵树都进行了约束,具体地,若树
f
k
f_k
fk有
T
T
T个叶结点,正则项包括对叶子个数的约束和叶子权值的L2范数。
Ω
(
f
k
)
=
γ
T
+
1
2
λ
∑
j
=
1
T
w
j
2
\Omega(f_k)=\gamma T+\frac{1}{2}\lambda \sum_{j=1}^Tw_j^2
Ω(fk)=γT+21λj=1∑Twj2
引入叶子节点个数的惩罚,等效于在回归树的生成过程中进行预剪枝。
剖析目标函数
XGBoost本质上是Tree Boosting,是一个迭代的过程,在第
t
t
t轮迭代,模型将累加上第
t
t
t棵树的预测:
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^i(t)=y^i(t−1)+ft(xi)
此时本轮的目标函数是下式,除了
f
t
f_t
ft以外的正则项可看作常数
O
b
j
(
t
)
=
∑
i
=
1
n
l
(
y
i
,
y
^
i
(
t
)
)
+
Ω
(
f
t
)
+
∑
k
≠
t
Ω
(
f
k
)
Obj^{(t)} =\sum_{i=1}^nl(y_i,\hat{y}_i^{(t)})+\Omega(f_t)+\sum_{k\neq t }\Omega(f_k)
Obj(t)=i=1∑nl(yi,y^i(t))+Ω(ft)+k̸=t∑Ω(fk)
为了更方便地计算,将
l
l
l在
y
^
i
(
t
−
1
)
\hat{y}_i^{(t-1)}
y^i(t−1)附近进行二阶泰勒展开(把
f
t
(
x
i
)
f_t(x_i)
ft(xi)看成
Δ
x
\Delta x
Δx)
l
(
y
i
,
y
^
i
(
t
)
)
=
l
(
y
i
,
y
^
i
(
t
−
1
)
+
f
t
(
x
i
)
)
≈
l
(
y
i
,
y
^
i
(
t
−
1
)
)
+
g
i
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
l(y_i,\hat{y}_i^{(t)})=l(y_i,\hat{y}_i^{(t-1)}+f_t(x_i))\\ \approx l(y_i,\hat{y}_i^{(t-1)})+g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)
l(yi,y^i(t))=l(yi,y^i(t−1)+ft(xi))≈l(yi,y^i(t−1))+gift(xi)+21hift2(xi)
其中
g
i
g_i
gi和
h
i
h_i
hi分别为一阶和二阶导数在上一次预测值处的取值,它们的计算取决于loss函数的选择,以均方误差
1
2
(
y
i
−
y
^
i
)
2
\frac{1}{2}(y_i-\hat{y}_i)^2
21(yi−y^i)2为例
{
g
i
=
∂
l
(
y
i
,
y
^
i
)
∂
y
^
i
∣
y
^
i
=
y
^
i
(
t
−
1
)
=
y
^
i
(
t
−
1
)
−
y
i
h
i
=
∂
2
l
(
y
i
,
y
^
i
)
∂
y
^
i
2
∣
y
^
i
=
y
^
i
(
t
−
1
)
=
1
\left\{ \begin{matrix} g_i=\frac{\partial l(y_i,\hat{y}_i)}{\partial \hat{y}_i}\left |\right._{\hat{y}_i=\hat{y}_i^{(t-1)}} & =\hat{y}_i^{(t-1)}-y_i\\ h_i=\frac{\partial^2 l(y_i,\hat{y}_i)}{\partial \hat{y}_i ^2}\left |\right._{\hat{y}_i=\hat{y}_i^{(t-1)}} &=1\end{matrix} \right.
⎩⎨⎧gi=∂y^i∂l(yi,y^i)∣y^i=y^i(t−1)hi=∂y^i2∂2l(yi,y^i)∣y^i=y^i(t−1)=y^i(t−1)−yi=1
于是本轮目标进一步写成下式(省略常数项,包括
l
(
y
i
,
y
^
i
(
t
−
1
)
)
l(y_i,\hat{y}_i^{(t-1)})
l(yi,y^i(t−1))也是确定的.)
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
f
t
(
x
i
)
+
1
2
h
i
f
t
2
(
x
i
)
]
+
γ
T
+
1
2
λ
∑
j
=
1
T
w
j
2
Obj^{(t)} =\sum_{i=1}^n\left [g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)\right ]+\Omega(f_t)\\ =\sum_{i=1}^n\left [g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)\right ]+\gamma T+\frac{1}{2}\lambda \sum_{j=1}^Tw_j^2
Obj(t)=i=1∑n[gift(xi)+21hift2(xi)]+Ω(ft)=i=1∑n[gift(xi)+21hift2(xi)]+γT+21λj=1∑Twj2
为了将两部分求和项结合起来,考虑将样本按照树
f
t
f_t
ft的叶结点划分,目标可写成关于
w
j
w_j
wj的凸二次函数
O
b
j
(
t
)
=
∑
j
=
1
T
[
(
∑
i
∈
I
j
g
i
)
w
j
+
1
2
(
∑
i
∈
I
j
h
i
+
λ
)
w
j
2
]
+
γ
T
Obj^{(t)} =\sum_{j=1}^T\left [\left ( \sum_{i\in I_j}g_i\right )w_j+\frac{1}{2}\left (\sum_{i\in I_j}h_i+\lambda\right ) w_j^2\right ]+\gamma T
Obj(t)=j=1∑T⎣⎡⎝⎛i∈Ij∑gi⎠⎞wj+21⎝⎛i∈Ij∑hi+λ⎠⎞wj2⎦⎤+γT
因此对于
f
t
f_t
ft的每一个叶子
j
j
j,目标在
w
∗
=
−
G
j
H
j
+
λ
w^*=-\frac{G_j}{H_j+\lambda}
w∗=−Hj+λGj处取得最小值:
O
b
j
(
t
)
∗
=
−
1
2
∑
j
=
1
T
G
j
2
H
j
+
λ
+
γ
T
Obj^{(t)*}=-\frac{1}{2}\sum_{j=1}^T\frac{G_j^2}{H_j+\lambda}+\gamma T
Obj(t)∗=−21j=1∑THj+λGj2+γT
2.3.3 回归树学习
回归树的学习(生成)策略
上文推导出,已知树
f
t
f_t
ft结构时,各叶子结点上的输出如何取值可使得本轮的优化效果最佳。于是问题转换为如何获得最佳的
f
t
f_t
ft结构,显然枚举所有树结构找出最优是不可能的,它是NP难问题。
贪婪构造法
贪婪构造的基本思想是,从根结点开始,尝试分裂结点,计算分裂前后的增益以判断是否分裂。这是一种贪心算法。
对任意结点进行分裂造成的
O
b
j
Obj
Obj减少量为下式,增益越大,分裂后为目标带来的优化越好,当然这个增益有可能为负
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}\left [ \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}\right ]-\gamma
Gain=21[HL+λGL2+HR+λGR2−HL+HR+λ(GL+GR)2]−γ
基于增益最大化的贪心树节点分裂方法(Split Searching)如下,近似法能减少计算复杂度,加快速度。
-
精确法
遍历所有特征及其候选分裂点,找出使得增益最大的最佳特征与最佳分裂点。具体地,将样本按照当前特征上的取值排序,遍历样本同时改变 G L G_L GL, G R G_R GR, H L H_L HL, H R H_R HR的值。 -
近似法
基本思路同上,但对于每个特征,只考虑分位点,减少计算复杂度。近似法可以有两种做法,其一是在训练整棵树前,提前为每个特征选择分位点,其二是在每个结点的分裂时,重新提出每个特征的候选切分点。
近似法中分位点的选取(Weighted Quantile Sketch)
XGBoost以二阶导数
h
i
h_i
hi作为每个样本的权重,选择分位数作为候选分裂点。原因是目标可以整理成如下形式,可看出
h
i
h_i
hi对于目标的加权作用。
O
b
j
=
∑
i
=
1
n
h
i
(
f
t
(
x
i
)
−
g
i
h
i
)
2
+
Ω
(
f
t
)
+
C
Obj=\sum_{i=1}^nh_i(f_t(x_i)-\frac{gi}{hi})^2+\Omega(f_t)+C
Obj=i=1∑nhi(ft(xi)−higi)2+Ω(ft)+C
例如样本按照特征
x
(
j
)
x^{(j)}
x(j)上的取值进行了排序,它们的
h
i
h_i
hi如下,选取三分位点:
x
(
j
)
:
x
1
x
2
x
3
∣
x
4
x
5
∣
x
6
h
i
:
0.1
0.1
0.1
∣
0.15
0.15
∣
0.3
\begin{matrix} x^{(j)}: & x_1 & x_2 & x_3 & | & x_4 & x_5 & | & x_6\\ h_i: & 0.1 & 0.1 & 0.1 & | & 0.15 & 0.15 & | & 0.3 \end{matrix}
x(j):hi:x10.1x20.1x30.1∣∣x40.15x50.15∣∣x60.3
因此选出
(
x
3
+
x
4
)
/
2
(x_3+x_4)/2
(x3+x4)/2和
(
x
5
+
x
6
)
/
2
(x_5+x_6)/2
(x5+x6)/2作为候补分裂点。
稀疏值特征处理
XGBoost中定义的稀疏,指类似one-hot的操作使得某些特征大量取值为0,或者因为样本在该特征上没有取值而用0取代。 XGBoost的做法是为有缺失值的特征学习一个默认的分裂方向。
具体地,对于每个包含缺失值的特征,认为缺失特征的样本在本特征取值相同,并且只关注该特征有取值的样本,分别模拟特征值缺失的样本被分到左右两个子结点的情况,用增益来衡量分裂的优劣。
####2.3.4 XGBoost系统设计
Column Block 存储与并行化
回归树生成最耗时的是结点分裂过程中对每个特征的排序操作。XGBoost的并行化并不是tree粒度的,而是特征粒度的,树之间仍然是串行依赖关系。
- 预排序与预存储
训练前,预先将样本按特征进行排序,以CSC的形式存入内存,各列是排序后的样本索引,且只存储非缺失样本。每次分裂时根据索引直接获得梯度。 - 并行化
特征之间各自计算互不影响,令各Block存储一到多个特征,即可实现并行化。
Cache-Aware Acess
XGBoost按照特征排序存储样本的索引,造成访问对应样本梯度时,内存的不连续访问,使速度变慢。为了解决这个问题:
- 对于精确法,预先把梯度按排序读取到一个buff中,使不连续变为连续访问。
- 对于近似法,调整block的大小(存储于block的样本量)
####2.3.5 其他特性
行采样 对样本采样。
列采样 对特征采样,参考随机森林。不再遍历所有特征,而是选择性地抽取一些候补特征进行遍历。
Shrinkage 即学习率缩减。每一轮学习到的树,再加入模型前要乘以一个系数,表示不完全相信。越到后面,对新树的信任度越小。
####2.3.6 一些常见问题的回答
【与传统GBDT相比,XGBoost有何不同】
-
基函数不同。GBDT只用CART树,XGBoost除了CART,也支持线性函数。
-
目标不同。具体体现在结点分裂策略与正则化。GBDT和XGBoost都是根据目标增益分裂结点,GBDT根据均方误差(回归)或基尼指数(分类),XGBoost则进一步引入正则项。
-
正则化不同。XGBoost定义正则化,包含了对叶子结点数的约束,以及叶子输出权值的L2范数,有利于防止过拟合。
-
利用导数阶数不同。GBDT只利用一阶导数,XGBoost利用一阶和二阶导数。这要求loss函数二阶可导,同时XGBoost支持自定义loss。用二阶导数的原因是可以加快收敛。
-
最佳特征选取策略不同。GBDT遍历所有特征,XGBoost引入类似于RandomForest的列(特征)子采样,有利于防止过拟合与加速运算。
-
候选分裂点选取策略不同。GBDT遍历特征的所有取值,XGBoost有两种做法,其一是遍历,其二是根据二阶导数选择样本分位点作为候补,类似于直方图算法。
-
Boosted模型构成不同。GBDT与XGBoost都是多棵回归树的加法模型,但XGBoost为每棵树设定了系数,表示不完全信任,有利于防止过拟合。
-
XGBoost引入了列采样,传统GBDT没有。
【XGBoost为什么那么快?】
-
预排序实现特征粒度的并行。
-
近似法避免遍历所有分裂点,只尝试分位点。
-
后来实现了类似于LightGBM的直方图算法,进一步加速。
【 XGBoost是怎么防止过拟合的?】
-
控制模型复杂度:正则化(L1和L2正则化),max_depth限制树的深度、min_child_weight和gamma参数限制进一步分裂。
-
给模型增加随机性:行列采样、学习率shrinkage。
【XGBoost怎么处理类别不均?】
-
若只关注预测的排序表现,可以用AUC作metric,然后用scale_pos_weight调整正负样本权重(负样本/正样本)
-
若关注预测概率的准确性,最好改变权重,可以改变max_delta_step(调成正数)来加速收敛。
【XGBoost如何进行切分点选择?】
贪心算法,具体地分为精确法和近似法,前者遍历特征的每一个取值,后者只按照二阶导数选取分位点进行切分。XGBoost后来也有直方图算法,应该比近似法要快一点。
【XGBoost构建树的时候是level-wise还是leaf-wise?】
贪心算法默认是level-wise,逐层分裂。若选用直方图算法,可以通过grow_policy选择depthwise或lossguide,前者优先分裂距离根最近叶子,实际上近似于level-wise,后者优先分裂loss减少量最多的结点,有点深度优先的味道,和lightgbm比较相似。
【 XGBoost有没有直方图算法?】
有,它的直方图算法也是将连续特征离散化。
【XGBoost怎么实现多分类?】
对于K分类,每一轮迭代训练K棵树,用softmax代入各树的输出以表示样本属于各类的概率。
【XGBoost怎么处理ID类特征?】
XGBoost并不直接支持ID类,如果输入ID类是数值型,会直接被当成具有大小关系的数值特征处理。
2.4 LightGBM
传统GBDT算法没有实现data fraction,每次分裂结点都需要对每个特征遍历整个数据集(遍历指测试分裂点而不是计算增益)。
XGBoost采用近似法,通过Global近似法预先选出分位点,避免多次遍历测试,但实际上并没有改变测试分裂点时的计算量,仍然要计算所有样本的梯度和,此外pre-sorted需要将整个数据集预读入内存,这限制了数据集的大小,若采用外存方法,频繁的IO操作会降低速度。
LightGBM提出了两个算法进一步加速GBDT,首先GOSS用于减少每次结点分裂参与训练的样本数量,其次EFB用于合并相互独立的特征从而达到降维的效果。两个算法均能在保证正确率基本不变的前提下,大幅提高计算速度。
2.4.1 GOSS (Gradient-Based One Side Sampling)
梯度决定重要性
GOSS的基本思想是,小梯度样本对目标的贡献小,大梯度样本对目标的贡献大。扔掉全部小梯度样本的做法不可取,但可以进行随机抽样。
算法
假设当前要分裂的结点上的样本为
I
I
I
设定两个比例:
a
a
a为大梯度样本抽样比,
b
b
b为小梯度样本抽样比
在每一轮分裂时对样本抽样:
- 按样本梯度的绝对值从大到小排列
- 取出前 a ∣ I ∣ a|I| a∣I∣个样本(大梯度),加上从剩下样本中随机抽取 b ∣ I ∣ b|I| b∣I∣个样本(小梯度),构成训练集
- 大梯度样本赋予权值1,小梯度样本赋予权值 1 − a b \frac{1-a}{b} b1−a,权值将在计算增益时乘到样本的梯度上
效果
理论上,若样本数量足够大,GOSS方法的泛化误差将与使用全部样本时接近。从算法的第2步看出,若
a
a
a和
b
b
b取值都较小,则每次分裂参与计算的样本都将远少于整个数据集,从而达到加速作用。
####2.4.2 EFB (Exclusive Feature Bundling)
特征独立性
EFB的思想是,将相互独立的特征捆绑在一起,称为exclusive bundle,从而减少特征个数。
- 独立性:如果两个特征从不同时 非0,则称他们独立(exclusive)
- 近似独立性:如果两个特征几乎不同时 非0,则称他们近似独立
特征捆绑算法
本算法的目的是决定将哪些特征捆绑在一起,EFB将特征捆绑问题转化为图着色问题。特征是无向图的顶点,特征之间若不相互独立,则存在边。
若允许近似独立性,可认为任意两个特征之间存在带权边,边上的权值等于特征之间冲突的个数(不同时取0的样本数),显然若两个特征从不同时取0,冲突(权值)会很大,即权值可看作顶点之间的距离,冲突大的两个特征之间原本是不应该有边的。(论文中给出的EFB算法与论文描述的不符,感觉有问题,此处留作以后细看代码后再做补充解释)。
####2.4.3 直方图算法
目前仍没有看懂,以后follow源代码。
2.4.4 对一些问题的解答
【LightGBM为什么快?】
- 采用直方图算法,在计算切分点增益时,只需按直方图bin划分并计算增益,时间复杂度是O(bin),XGBoost的预排序(默认精确法)虽然不需要每次都重新排序,但需要对每个样本切分位置计算,复杂度O(data)。另外,虽然一开始LightGBM构造直方图也需要O(data)的时间,但XGBoost精确法预排序一般也要O(NlogN),所以还是LightGBM快。不过XGBoost支持近似法,复杂度是O(分位点),另外也支持直方图算法,因此应该不比LightGBM慢。
- 直方图减法。LightGBM在根节点使用预生成的直方图,然后每次结点分裂时,只计算样本少的儿子的直方图,然后另一个儿子用父节点直方图减去算好的直方图即可。因此每次分裂的效率更高。实际上XGBoost也可以采用这个方式,不知道为什么不做。
- GOSS。只保留二阶梯度大的样本,对梯度小的样本随机采样,于是每次参与计算的样本很少。但是这个模式是可选的,默认还是gbdt,也就是说默认仍是选取所有样本参与训练的。
【LightGBM为什么节省内存?】
LightGBM只保存离散的直方图,没有XGBoost的预排序操作。
【 LightGBM的树生长策略是level-wise还是leaf-wise?】
leaf-wise,总是选择当前loss下降最多的叶子结点进行分裂,以使整体模型下降地更多,更快收敛。但容易造成过拟合,通常需要调整max_depth来防止。XGBoost目前既支持level-wise(默认)又支持leaf-wise(hist)。
【LightGBM如何处理ID类特征?】
LightGBM支持ID类直接作为输入,结点分裂的时候仍然是利用直方图算法测试分裂点,用于计算增益的仍然是直方图各个bin中的二阶梯度和,实际上就是将ID类作为数值类处理,但特征值没有参与运算。
2.4.5 XGBoost vs LightGBM
【区别】
-
树的切分策略不同
XGBoost是level-wise,LightGBM是leaf-wise -
加速(实现并行)的方式不同
XGBoost是通过预排序方式,LightGBM主要是通过直方图相关的算法 -
对Categorical Feature的支持不同
XGBoost不支持类别特征输入。LightGBM支持输入类别特征,对类别特征不需要OneHot。 -
特征并行不同
XGBoost多机器并行时各机器只保留不同的特征子集,分别找到局部最优分裂点,后互相通信来找到全局最优,然后切分并传递切分结果。LightGBM每个机器保存完整数据集,无需相互传输切分结果。 -
lgbm引入了DART选项
DART可以理解为带有dropout的GBDT,没有做过多的了解。
三、参考文献与相关链接
【书籍】《统计学习方法》李航
【书籍】《机器学习》周志华
【书籍】《最优化计算方法》蒋金山
【书籍】《工科数学分析》
【API】Xgboost
【API】Xgboost参数
【PPT】Xgboost Slides
【博客】Xgboost Slides中文讲解
【论文】Xgboost原论文 XGBoost: A Scalable Tree Boosting System
【论文】DART论文 DART: Dropouts meet Multiple Additive Regression Trees
Wepon-XGBoost深入浅出
【博客】Wepon-GBDT算法原理与系统设计简介
【博客】GBDT详解-火光摇曳
【论文】LightGBM原论文 LightGBM-A Highly Efficient Gradient Boosting Decision Tree
【API】LightGBM官方文档——特性
【博客】GBDT:梯度提升决策树
【博客】GBDT原理小结