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 二阶可导。
举个例子,在迭代算法中,往往有 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 基本介绍
梯度下降法,或最速下降法,属于利用一阶导数的无约束目标最优化方法。基本思想是,在每一次迭代中,使用负梯度方向为搜索(更新)方向。
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 基本介绍
牛顿法属于利用一阶导数和二阶导数的无约束目标最优化方法。基本思想是,在每一次迭代中,以牛顿方向(一阶与二阶之比取负)为搜索方向进行更新。牛顿法对目标的可导性更严格,要求二阶可导,有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]
利用上面的迭代公式进行更新。
CART(classification and regression tree)树是决策树的一种,既可以实现分类也可以实现回归,正是它命名的由来。它规定树的结构是二叉树,每个结点上的分叉条件形似 “ I D = s ID=s ID=s ?” 或者 “ A < a A<a A<a ?”。特征选择策略为,分类树 采用基尼指数最小化准则,回归树 采用平方误差最小化准则。
CART回归树的构建是一个递归的过程。CART回归树的每个结点(包括中间结点和根)都有一个输出,他等于结点中所有样本的输出平均值。对于一棵训练好的CART回归树,总能将待测样本分到某个叶子结点上,模型关于该样本的输出,正是该叶子结点输出的权值。
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)
为了求各单元最优输出,首先要确定如何划分(分裂)。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 的最佳分裂。
遍历特征 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。
概率分布的基尼指数【定义】:
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 仍存在的不确定性。
【基尼指数越小越好】
假设分到当前结点的样本集为 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.1 简介
Boosting属于集成学习(Ensemble)的一种,是一种将一系列弱学习器提升为一个强学习器的方法,工作机制基本上是每次迭代从训练集训练出一个基学习器,然后根据本次迭代基学习器的性能,调整训练集样本的分布,或者改变拟合的目标,使得后续的基学习器更多地去关注之前的基学习器判断错误的样本。最终,学习器之间的组合采用加法模型,即基函数的加权线性组合。
常用的Boosting算法包括Adaboost、提升树、gbdt等等。
Boosting算法要求基学习器能对特定的数据分布进行学习,从偏差-方差(bias-variance)的角度看,Boosting更关注降低偏差,因此Boosting能基于泛化能力很弱的基学习器构造出很强的集成模型。
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个元素表示第三列。从例子似乎看不出稀疏表示的优越性,实际上当各列足够稀疏(例如上万行只有几个非零元素)时才能显出。
提升树以决策树为基函数的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)
以下为 提升回归树算法:
下面用一个只有一维特征的例子举例说明如何训练 提升回归树
| 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 的残差其实已经很小了,如此继续下去迭代若干次得到的叠加模型,就是最终的提升树模型。
当损失函数是平方损失时,每一轮计算残差是简单的,对于一般的损失函数可能不是那么友好(比如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)
负梯度是loss下降最快的方向,每一个基函数去拟合负梯度,最终的叠加也是loss下降最快的方向。普通的提升树之所以拟合残差,实际上是因为它使用平方误差,其梯度正式残差,因此可以将残差理解为负梯度在loss函数使用平方误差时的特例。使用负梯度作为拟合目标的好处在于,能更快地收敛,以及更具有普适性,即适用于更多的loss形式,而不拘泥与平方误差。
首先是树模型所具备的一些共有的优点
GBDT的优点
GBDT的缺点
RF的优点
RF的缺点
回归树
回归树的每个叶子结点都有其对应的分数(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)
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
回归树的学习(生成)策略
上文推导出,已知树 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粒度的,而是特征粒度的,树之间仍然是串行依赖关系。
Cache-Aware Acess
XGBoost按照特征排序存储样本的索引,造成访问对应样本梯度时,内存的不连续访问,使速度变慢。为了解决这个问题:
####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类是数值型,会直接被当成具有大小关系的数值特征处理。
传统GBDT算法没有实现data fraction,每次分裂结点都需要对每个特征遍历整个数据集(遍历指测试分裂点而不是计算增益)。
XGBoost采用近似法,通过Global近似法预先选出分位点,避免多次遍历测试,但实际上并没有改变测试分裂点时的计算量,仍然要计算所有样本的梯度和,此外pre-sorted需要将整个数据集预读入内存,这限制了数据集的大小,若采用外存方法,频繁的IO操作会降低速度。
LightGBM提出了两个算法进一步加速GBDT,首先GOSS用于减少每次结点分裂参与训练的样本数量,其次EFB用于合并相互独立的特征从而达到降维的效果。两个算法均能在保证正确率基本不变的前提下,大幅提高计算速度。
梯度决定重要性
GOSS的基本思想是,小梯度样本对目标的贡献小,大梯度样本对目标的贡献大。扔掉全部小梯度样本的做法不可取,但可以进行随机抽样。
算法
假设当前要分裂的结点上的样本为 I I I
设定两个比例: a a a为大梯度样本抽样比, b b b为小梯度样本抽样比
在每一轮分裂时对样本抽样:
效果
理论上,若样本数量足够大,GOSS方法的泛化误差将与使用全部样本时接近。从算法的第2步看出,若 a a a和 b b b取值都较小,则每次分裂参与计算的样本都将远少于整个数据集,从而达到加速作用。
####2.4.2 EFB (Exclusive Feature Bundling)
特征独立性
EFB的思想是,将相互独立的特征捆绑在一起,称为exclusive bundle,从而减少特征个数。
特征捆绑算法
本算法的目的是决定将哪些特征捆绑在一起,EFB将特征捆绑问题转化为图着色问题。特征是无向图的顶点,特征之间若不相互独立,则存在边。
若允许近似独立性,可认为任意两个特征之间存在带权边,边上的权值等于特征之间冲突的个数(不同时取0的样本数),显然若两个特征从不同时取0,冲突(权值)会很大,即权值可看作顶点之间的距离,冲突大的两个特征之间原本是不应该有边的。(论文中给出的EFB算法与论文描述的不符,感觉有问题,此处留作以后细看代码后再做补充解释)。
####2.4.3 直方图算法
目前仍没有看懂,以后follow源代码。
【LightGBM为什么快?】
【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类作为数值类处理,但特征值没有参与运算。
【区别】
树的切分策略不同
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原理小结