GBM

GBM

决策树章节中,学习了单棵决策树算法。但是单棵决策树模型效果往往不是很好,自然的就会想到集成多棵决策树的来得到最终的结果。本文主要讲述GBM算法,并以XGBoost为例介绍Boost Trees,然后介绍XGBoost和LightGBM算法中的一些细节。GBM算法中,弱分类器使用的都是CART回归树。

目标函数

每个算法训练的时候都会有它的目标函数,算法训练过程就是在训练集上求目标函数的最优解的过程,目标函数的值代表的是它拟合训练集的程度。在决策树中虽然没有明确的定义目标函数,但是其实它的目标函数就是基于信息熵/信息增益/gini系数等定义的。在学习XGBoost之前,我们先明确的定义一下目标函数。

首先,目标函数需要包含损失函数(经验风险),损失函数衡量的是预测结果与真实结果的差异。比如分类模型中的信息熵、信息增益,回归模型中的均方误差等都可以作为损失函数。其次,目标函数需要包含正则项,或者说结构风险函数,结构风险函数衡量的是模型的复杂程度,用于控制模型过拟合。决策树中控制树生长的最大深度,回归函数中的二次项正则等都是正则项。结合起来,目标函数应该是如下的形式:
O b j ( F ) = L ( F ) + Ω ( F ) Obj(F)=L(F)+\Omega(F) Obj(F)=L(F)+Ω(F)
如图所示,一个合理的目标函数,需要合理的平衡经验风险和结构风险(图片来自xgboost官方文档)。
在这里插入图片描述

决策树中的参数

线性回归模型中的系数是很容易理解的模型参数,那么决策树模型中的模型参数是什么呢?

  • 树的结构,即树的结点数、每一个结点的分割依据等;
  • 叶子节点得分,即叶子节点样本预测值。

模型集成

在模型集成中,加法模型是最常用的。假设有T个模型 { f t ∣ t = 1 , 2 , . . . , T } \{f_t|t=1,2,...,T\} {ftt=1,2,...,T},集成T个模型的结果为
F T = ∑ t = 1 T f t F_T=\sum_{t=1}^Tf_t FT=t=1Tft
随机森林和Boosting都是使用加法模型来集成多个模型的。不同的是F的训练方法不同。在随机森林中,每一个 f t f_t ft是独立训练的:
O b j ( F t ) = { O b j ( f i ) ∣ i = 1 , 2 , . . . , t } Obj(F_t)=\{Obj(f_i)|i=1,2,...,t\} Obj(Ft)={Obj(fi)i=1,2,...,t}
在Boosting中 f t f_t ft是串行训练的,每个 f t f_t ft都在 { f i ∣ i = 1 , 2 , . . , ( t − 1 ) } \{f_i|i=1,2,..,(t-1)\} {fii=1,2,..,(t1)}训练结果的基础上训练的:
O b j ( F t ) = O b j ( F t − 1 + f t ∣ F t − 1 ) Obj(F_t)=Obj(F_{t-1}+f_t|F_{t-1}) Obj(Ft)=Obj(Ft1+ftFt1)
根据分类器f的不同,f的训练方式不同,损失函数L的不同等,Boosting也分成AdaBoost,XGboost,LightGBM等模型。

XGBoost

XGBoost是“Extreme Gradient Boosting”的缩写,其中“Gradient Boosting”一词在论文 ≪ < < G r e e d y F u n c t i o n A p p r o x i m a t i o n : A G r a d i e n t B o o s t i n g M a c h i n e ≫ \ll <<Greedy Function Approximation: A Gradient Boosting Machine\gg <<GreedyFunctionApproximation:AGradientBoostingMachine中,由 Friedman 提出,XGBoost 是基于这个原始模型做的一个实现。

目标函数

o b j ( t ) = ∑ i = 1 n l ( y i , y i ^ ( t ) ) + ∑ i = 1 t Ω ( f i ) obj^{(t)}=\sum_{i=1}^nl(y_i,\hat{y_i}^{(t)})+\sum_{i=1}^t{\Omega(f_i)} obj(t)=i=1nl(yi,yi^(t))+i=1tΩ(fi)
其中 y i ^ ( t ) \hat{y_i}^{(t)} yi^(t)表示模型 F t F_t Ft对样本i的预测结果。

模型训练

不同于AdaBoost对基分类器没有要求,XGBoost是一个基分类器为决策树的Boosting模型。Boosting训练 f t f_t ft都是在 F t − 1 F_{t-1} Ft1已经训练好的前提下训练的,对于决策树的参数:树的结构和叶子节点得分,在训练决策树参数时,不同于传统的决策树算法,此时叶子节点得分使用梯度下降的方法训练。

作为一个串行的训练算法,对于样本i,初始化 y i ^ ( 0 ) = 0 \hat{y_i}^{(0)}=0 yi^(0)=0,有如下的训练过程:
y i ^ ( 1 ) = f 1 ( x 1 ) = y i ^ ( 0 ) + f 1 ( x i ) \hat{y_i}^{(1)}=f_1(x_1)=\hat{y_i}^{(0)}+f_1(x_i) yi^(1)=f1(x1)=yi^(0)+f1(xi)
y i ^ ( 2 ) = f 1 ( x i ) + f 2 ( x i ) = y i ^ ( 1 ) + f 2 ( x i ) \hat{y_i}^{(2)}=f_1(x_i)+f_2(x_i)=\hat{y_i}^{(1)}+f_2(x_i) yi^(2)=f1(xi)+f2(xi)=yi^(1)+f2(xi)
. . . ... ...
y i ^ ( t ) = ∑ j = 1 t f j ( x i ) = y i ^ ( t − 1 ) + f t ( x i ) \hat{y_i}^{(t)}=\sum_{j=1}^tf_j(x_i)=\hat{y_i}^{(t-1)}+f_t(x_i) yi^(t)=j=1tfj(xi)=yi^(t1)+ft(xi)
其中 f t ( x i ) f_t(x_i) ft(xi)表示样本 x i x_i xi在第t棵树所在叶子结点的预测值。此时
KaTeX parse error: No such environment: eqnarray at position 7: \begin{̲e̲q̲n̲a̲r̲r̲a̲y̲}̲ obj^{(t)} &=& …
考虑到在优化 f t f_t ft时,前t-1棵树都已经训练完毕, o b j ( t ) obj^{(t)} obj(t)中与 f t f_t ft无关的项都可作为常数项。若此时的loss函数为MSE,则有:
o b j ( t ) = ∑ i = 1 n ( y i − ( y i ^ ( t − 1 ) + f t ( x i ) ) ) 2 + ∑ i = 1 t Ω ( f i ) = ∑ i = 1 n ( − 2 ( y i − y i ^ ( t − 1 ) ) f t ( x i ) + f t ( x i ) 2 ) + Ω ( f t ) + c o n s t a n t \begin{aligned} obj^{(t)} &=& \sum_{i=1}^n(y_i-(\hat{y_i}^{(t-1)}+f_t(x_i)))^2+\sum_{i=1}^t{\Omega(f_i)}\\ &=& \sum_{i=1}^n(-2(y_i-\hat{y_i}^{(t-1)})f_t(x_i)+{f_t(x_i)}^2)+\Omega(f_t)+constant \end{aligned} obj(t)==i=1n(yi(yi^(t1)+ft(xi)))2+i=1tΩ(fi)i=1n(2(yiyi^(t1))ft(xi)+ft(xi)2)+Ω(ft)+constant
在实际使用的时候,不可能总是使用MSE这种可以直接多项式展开的函数(如分类问题常用的logistic loss),但是对于可导的损失函数,可以使用泰勒展开得到其多项式逼近的函数(附录一)。在XGBoost中,使用基于二阶泰勒展开的梯度下降来优化目标函数,将损失函数在 y i ^ ( t − 1 ) \hat{y_i}^{(t-1)} yi^(t1)做二阶泰勒展开。此时
o b j ( t ) = ∑ i = 1 n l ( y i , y i ^ ( t − 1 ) + f t ( x i ) ) + ∑ i = 1 t Ω ( f i ) ≈ ∑ i = 1 n ( l ( y i , y i ^ ( t − 1 ) ) + g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ) + Ω ( f t ) + c o n s t a n t = ∑ i = 1 n ( g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ) + Ω ( f t ) + c o n s t a n t \begin{aligned} obj^{(t)} &=& \sum_{i=1}^nl(y_i,\hat{y_i}^{(t-1)}+f_t(x_i))+\sum_{i=1}^t{\Omega(f_i)}\\ &\approx& \sum_{i=1}^n(l(y_i,\hat{y_i}^{(t-1)})+g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i))+\Omega(f_t)+constant\\ &=& \sum_{i=1}^n(g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i))+\Omega(f_t)+constant \end{aligned} obj(t)==i=1nl(yi,yi^(t1)+ft(xi))+i=1tΩ(fi)i=1n(l(yi,yi^(t1))+gift(xi)+21hift2(xi))+Ω(ft)+constanti=1n(gift(xi)+21hift2(xi))+Ω(ft)+constant
其中
g i = ∂ l ( y i , y i ^ ) ∂ y i ^ ∣ y i ^ = y i ^ ( t − 1 ) g_i=\frac{\partial l(y_i, \hat{y_i})}{\partial \hat{y_i}}|_{\hat{y_i}=\hat{y_i}^{(t-1)}} gi=yi^l(yi,yi^)yi^=yi^(t1)
h i = ∂ 2 l ( y i , y i ^ ) ∂ y i ^ 2 ∣ y i ^ = y i ^ ( t − 1 ) h_i=\frac{\partial^2 l(y_i, \hat{y_i})}{\partial \hat{y_i}^2}|_{\hat{y_i}=\hat{y_i}^{(t-1)}} hi=yi^22l(yi,yi^)yi^=yi^(t1)
至此,XGBoost的优化目标中,包含优化函数关于预测结果的一阶导函数 g i g_i gi和二阶导函数 h i h_i hi。换句话说,无论任何损失函数,只要损失函数能在 y i ^ ( t − 1 ) \hat{y_i}^{(t-1)} yi^(t1)的某个闭区间内做二阶泰勒展开,那么它就能使用以上方法做优化。

XGBoost中,对于分类问题,损失函数默认的是Softmax-logistic loss;对于回归问题,损失函数默认使用MSE。需要注意的是,由于数值稳定性(附录二),对于分类问题,损失函数需要包含sigmoid/softmax层,计算 g i g_i gi h i h_i hi时需要使用的 y i ^ \hat{y_i} yi^是做sigmoid/softmax前的函数。XGBoost支持自定义损失函数

模型复杂度

模型训练中只讨论了损失函数,还有很重要的一部分 Ω ( f t ) \Omega(f_t) Ω(ft)。假设第t棵树为:
f t ( x ) = w q ( x ) , w ∈ R T , q = R d → { 1 , 2 , . . . , T } f_t(x)=w_{q(x)},w \in R^T,q=R_d \rightarrow \{1,2,...,T\} ft(x)=wq(x),wRT,q=Rd{1,2,...,T}
其中 w w w表示叶子节点得分, q q q是一个函数,将每个数据点映射到对应叶子节点的函数,T是叶子节点个数,d为特征维度。在XGBoost中,定义的结构风险函数为:
Ω ( f t ) = γ T + 1 2 λ ∑ j = 1 T w j 2 \Omega(f_t)=\gamma T+\frac{1}{2}\lambda \sum_{j=1}^Tw_j^2 Ω(ft)=γT+21λj=1Twj2
决策树的结构风险并不是只有这一种定义方法,比如“树的深度”也可以作为结构风险的一项。XGBoost使用这个作为正则项,一方面是因为直白,更重要的是因为好用。另一方面,XGBoost将 γ \gamma γ λ \lambda λ作为模型训练的超参,但是XGboost并没有给自定义正则函数的接口,所以使用XGBoost算法时,并不能自定义正则化函数。

最终的目标函数

结合损失函数和正则项,最终的目标函数为:
o b j ( t ) ≈ ∑ i = 1 n ( g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ) + Ω ( f t ) + c o n s t a n 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 + c o n s t a n t = ∑ j = 1 T ( ( ∑ i ∈ I j g i ) w j + 1 2 ( ∑ i ∈ I j h i + λ ) w j 2 ) + γ T + c o n s t a n t \begin{aligned} obj^{(t)} &\approx& \sum_{i=1}^n(g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i))+\Omega(f_t)+constant\\ &=& \sum_{i=1}^n(g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i))+\gamma T+\frac{1}{2}\lambda \sum_{j=1}^Tw_j^2+constant\\ &=& \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+constant \end{aligned} obj(t)==i=1n(gift(xi)+21hift2(xi))+Ω(ft)+constanti=1n(gift(xi)+21hift2(xi))+γT+21λj=1Twj2+constantj=1T((iIjgi)wj+21(iIjhi+λ)wj2)+γT+constant
其中 I j = { i ∣ q ( x i ) = j } I_j=\{i|q(x_i)=j\} Ij={iq(xi)=j}表示被划分到叶子节点j的数据点。以上第三个等式改变了最外层的求和符号,原因就在于同一个叶子节点数据点映射后的值都为该叶子节点的得分。这样变换的还有一个好处就是在树的生长过程中,使得之前的计算可以复用。定义 G j = ∑ i ∈ I j g j G_j=\sum_{i \in I_j}g_j Gj=iIjgj, H j = ∑ i ∈ I j h i H_j=\sum_{i \in I_j}h_i Hj=iIjhi,可以得到:
o b j ( t ) ≈ ∑ j = 1 T ( G j w j + 1 2 ( H j + λ ) w j 2 ) + γ T + c o n s t a n t obj^{(t)} \approx \sum_{j=1}^T(G_jw_j+\frac{1}{2}(H_j+\lambda)w_j^2)+\gamma T+constant obj(t)j=1T(Gjwj+21(Hj+λ)wj2)+γT+constant
模型参数训练的时候不用考虑常数项,即:
o b j ( t ) ≈ ∑ j = 1 T ( G j w j + 1 2 ( H j + λ ) w j 2 ) + γ T obj^{(t)} \approx \sum_{j=1}^T(G_jw_j+\frac{1}{2}(H_j+\lambda)w_j^2)+\gamma T obj(t)j=1T(Gjwj+21(Hj+λ)wj2)+γT
公式中每个 w w w都是相互独立的,所以为了求 o b j ( t ) obj^{(t)} obj(t)的极小值,对于关于 w w w的二次多项式,有:
w j ∗ = − G j H j + λ w_j^*=-\frac{G_j}{H_j+\lambda} wj=Hj+λGj
o b j ∗ = − 1 2 ∑ j = 1 T G j 2 H j + λ + γ T obj^*=-\frac{1}{2}\sum_{j=1}^T\frac{G_j^2}{H_j+\lambda}+\gamma T obj=21j=1THj+λGj2+γT
其中 o b j ∗ obj^* obj就代表了函数 q ( x ) q(x) q(x)的效果, o b j ∗ obj^* obj越小,表示效果越好。不同于传统决策树的信息熵、信息增益等评价标准,XGBoost中以 o b j ∗ obj^* obj的值作为属性选择的评价标准。注意这里的 w j ∗ w_j^* wj,它相当于一个负的梯度乘以一个系数,类似于一阶泰勒展开的梯度下降,但是它乘的系数包含了二次项,二次项的系数越大,系数值越小。直观上解释,二次项系数越大,代表的是梯度变化剧烈,也就是说一点点的改变,梯度可能就会变换很大,所以这些数据对应的系数就要小一些,让数据变化的小一点。
如图所示,即为一个 o b j ∗ obj^* obj的计算例子(图片来自xgboost官方文档):
在这里插入图片描述

属性选择

当一个节点按照新的属性分为左右节点时,得到的增益为:
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}[\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}]-\gamma Gain=21[HL+λGL2+HR+λGR2HL+HR+λ(GL+GR)2]γ
选择最佳的增益作为节点的划分属性。注意到 G a i n Gain Gain中的最后一项 γ \gamma γ,它相当于对新分节点的惩罚,类似决策树中的一种剪枝手段,即当新分割节点时,只有当左右节点的 G a i n Gain Gain之和与原始节点的 G a i n Gain Gain之差大于 λ \lambda λ时,划分得到的收益才是正的。

XGBoost中的一些细节

  • pre-sort。Boosting是串行的操作,不能并行生成每一棵树。但是决策树的算法最耗时的是选择最佳属性,而选择最佳属性是可以并行的。XGBoost对所有属性预排序,即对你每一个属性,按照属性大小对样本做一个排序,得到一个新的序列数据,并将其保存在内存空间中(占用的空间大小相当于原始数据的两倍)。在选择最佳属性的时候,调用这些已经排序好的序列,计算 G a i n Gain Gain。相比较于传统GBM算法,速度提高很多。
  • XGBoost的决策树默认按照层生长的。
  • XGBoost在决策的生成过程中,在设置好Depth后,决策树是后剪枝的。
  • 缺失值处理,自动的确定分裂方向。训练时将缺失值分别分入左右子树计算损失,然后确定缺失值的划分方向。如果在训练中没有缺失值而在预测中出现缺失,那么会自动将缺失值的划分方向放到右子树。
参数说明

详细的参数说明见官方参数说明,这里列一些重要参数。

  • eta/learning rate/Shrinkage,学习率,在学习完一棵树以后,将叶子得分乘以这个数,用以降低该棵数的影响,可以认为也是正则化的一种重要手段。
  • max_depth,树的最大深度
  • min_child_weight,叶子节点的最小weight (hessian) 之和。叶子节点和小于这个值,则节点不再分裂。
  • gamma
  • lambda,正则手段之一。
  • subsample,行抽样,每棵决策树使用的样本比例,正则手段之一。
  • colsample_bytree,列抽样,每棵决策树使用的属性比例,正则手段之一。
  • tree_method,决策树的训练方法,常用’auto’,‘hist’,‘gpu_hist’。默认的是‘pre-sort’,‘hist’为与LightGBM相同的直方图算法,速度快很多。‘gpu_hist’是使用gpu训练,速度更快。
  • objective。如‘binary:logistic’,'reg:squarederror’等
  • eval_metric ,评估函数。
  • num_round,最大的数的数量
  • early_stopping_rounds,提前终止,正则手段之一。

一些使用案例见官方文档

模型对比

虽然同是GBM算法的工程实现,但是传统GBDT、XGBoost和LightGBM间也有很多差异。如:

  • 是否在损失函数中加入结构风险
  • 使用一阶泰勒展开还是二阶泰勒展开的梯度下降
  • 是否加入类似Random Forest中的行抽样和列抽样
    差别点有很多,虽然现在的XGBoost、LightGBM库都各自为不同的想法提供了接口。不过本节介绍还是介绍一下原始的XGBoost和LightGBM中的一些不同点。LightGBM的官方文档中更多详细说明,项目中有一些使用例子。

直方图算法

在LightGBM算法中,为了选择最佳的属性分割收益,使用的是直方图算法,二并不是XGboost使用的预排序算法。直方图算法在使用的时候首先需要将所有的数据点转化成bin,即对每个特征的取值做个分段函数,然后将所有的样本在该特征上的取值划分到不同的bin中,最终把连续特征值转化为离散值。划分bin后的直方图算法如下图所示:
在这里插入图片描述

  • 直方图算法将n个数据划分到k个bin中,一般情况下k比n小很多。在bin划分完毕之后,之后的计算都是基于bin做的,时间复杂度从o(#data)降低到o(#bin)。
  • 直方图算法不需要对所有特征做预排序,它直接遍历所有特征,寻找最佳分割。
  • 直方图算法中每个bin存储了bin中样本的梯度之和以及每个bin中的样本数量,存储信息少,占用内存小,也利于多机器并行训练时的通信。
  • 直方图算法在选择分割点时,遍历当前属性的所有bin,累计其左边的bin的梯度之和和样本数量之和,右边的梯度之和与样本数量之和可以通过父节点与左节点的差得到,以此省了一半的时间。然后计算分割增益,以求得最大的增益。

直方图算法需要的内存显著降低,计算代价也大幅降低;直方图算法对于缺失值处理时不能类似于XGBoost中的自动划分缺失值的划分方向,LightGBM构建直方图时不使用缺失值特征;直方图算法相比较于预排序,采用bin的方式降低内存,降低计算,会导致分割精度变差点,但是对最后的结果影响不大。可能因为决策树是弱分类器,分割点精度对决策树可能也不是太重要,也可能,较粗的分割点也有正则化的效果,能防止过拟合,还可能单棵树的训练误差大点,但是在梯度提升的框架下没有太大影响。

类别特征处理

GBDT算法中,决策树的分割都是分成左叶子节点和右叶子节点两类的。这种分类方法对于连续值来说很好处理,选择一个最佳的分割点就行,但是对于离散值来说就比较难以处理了。一般通用的处理方法是讲离散数据做one-hot编码,XGBoost中使用的也是one-hot编码。one-hot编码意味着在每一个决策节点只能使用one vs res的切分方式,当类别数量多的时候,切分出的左右节点的数据会很不平衡,每次切分的收益会很小。再加上决策树学习的时候利用的是统计信息,统计信息在数据小的时候是较可能不准确的。基于直方图的算法可以有另一种处理方式,将该类别特征所有的类别bin中的sum_gradient/sum_hessian值从小到大排序,然后按照结果依次枚举最优分割点。这样分割点左叶子节点和右叶子节点都可能包含many个特征类别,这样的方式比较容易过拟合,所有LightGBM在实现上添加了许多正则手段,如忽略出现次数较少的特征值、只在类别数量较多时使用many vs many的分割方式等。

决策树中的level-wise和leaf-wise

level-wise指的是在决策树的生长过程中,每一次对同一层的所有可分割的叶子节点做分割。XGBoost和其它一般的决策树算法都是使用这种生长策略的。而leaf-wise是每一次只对所有可分割叶子节点中的一个节点做分割。level-wise过一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上level-wise它不加区分的对待同一层的叶子,带来了很多没必要的开销,实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。leaf-wise在分裂次数相同的情况下,可以降低更多的误差,得到更好的精度。leaf-wise的缺点是可能会长出比较深的决策树,产生过拟合。因此LightGBM在leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。一般使用level-wise的决策树生长过程中有max_depth超参控制过拟合,而leaf-wise生长的决策树,除了max_depth,还有max_leaf用于控制过拟合,max_leaf的取值会小于 2 m a x d e p t h 2^{max_depth} 2maxdepth(实际使用的时候一般小很多)。

并行

特征并行

特征并行算法目的是在决策树生成过程中的每次迭代,高效地找到最优特征分裂点。特征并行的主要思想是在不同机器在不同的特征集合上分别寻找最优的分割点,然后在机器间同步最优的分割点。

传统的特征并行算法

  1. 根据不同的特征子集,将数据集进行垂直切分。(不同机器worker有不同的特征子集)
  2. 每个worker寻找局部的最优分裂特征以及分裂点。
  3. 不同worker之间进行网络传输,交换最优分裂信息,最终得到最优的分裂信息。
  4. 具有最优分裂特征的worker,局部进行分裂,并将分裂结果广播到其他worker。
  5. 其他worker根据接收到的数据进行切分数据。

该方法不能有效地加速特征选择的效率,当数据量#data很大时,该并行方法不能加快效率。并且,最优的分裂结果需要在worker之间进行传输,需要消耗很多的传输资源以及传输时间。

LightGBM的特征并行算法

LightGBM并没有垂直的切分数据集,而是每个worker都有全量的训练数据,因此最优的特征分裂结果不需要传输到其他worker中,只需要将最优特征以及分裂点告诉其他worker,worker随后本地自己进行处理。处理过程如下:

  1. 每个worker在基于局部的特征集合找到最优分裂特征。
  2. workder间传输最优分裂信息,并得到全局最优分裂信息。
  3. 每个worker基于全局最优分裂信息,在本地进行数据分裂,生成决策树。

然而,当数据量很大时,特征并行算法还是受限于特征分裂效率。因此,当数据量大时,推荐使用数据并行算法。

数据并行

传统的数据并行算法

  1. 水平切分数据集。
  2. 每个worker基于数据集构建局部特征直方图(Histogram)。
  3. 归并所有局部的特征直方图,得到全局直方图。
  4. 找到最优分裂信息,进行数据分裂。

缺点:网络传输代价比较大,如果使用point-to-point的传输算法,每个worker的传输代价为O(#machine * #feature * #bin). 如果使用All Reduce并行算子,传输代价为O(2* #feature * #bin).

LightGBM的数据并行算法

  1. LightGBM算法使用Reduce Scatter并行算子归并来自不同worker的不同特征子集的直方图,然后在局部归并的直方图中找到最优局部分裂信息,最终同步找到最优的分裂信息。
  2. LightGBM使用直方图减法加快训练速度。我们只需要对其中一个子节点进行数据传输,另一个子节点可以通过histogram subtraction得到。
  3. LightGBM可以将传输代价降低为O(0.5 * #feature * #bin)。

基于投票的并行算法
基于投票机制的并行算法,是在每个worker中选出top_k个分裂特征,然后将每个worker选出的k个特征进行汇总,并选出全局分裂特征,进行数据分裂。有理论证明,这种voting parallel以很大的概率选出实际最优的特征,因此不用担心top_k的问题。

附录

附录一 泰勒展开

若函数f(x)在包含 x 0 x_0 x0的某个闭区间[a,b]上具有n阶导数,且在开区间(a,b)上具有(n+1)阶导数,则对闭区间[a,b]上任意一点x,成立下式:
f ( x ) = ∑ i = 0 n f ( i ) ( x 0 ) i ! ( x − x 0 ) n + o ( ( x − x 0 ) n ) f(x)=\sum_{i=0}^n{f^{(i)}(x_0) \over i!}(x-x_0)^n+o((x-x_0)^n) f(x)=i=0ni!f(i)(x0)(xx0)n+o((xx0)n)

基于一阶泰勒展开的梯度下降

在模型训练的时候一般是求目标函数的最小值,在不考虑正则项的情况下,我们先考虑求损失函数的最小值。假设已知 l ( x 0 ) l(x_0) l(x0)的值,以及 l ( 1 ) ( x 0 ) l^{(1)}(x_0) l(1)(x0),则 l ( x ) l(x) l(x) x 0 x_0 x0处的一阶泰勒展开为:
l ( x ) = l ( x 0 ) + l ( 1 ) ( x 0 ) ( x − x 0 ) + o ( x − x 0 ) l(x)=l(x_0)+l^{(1)}(x_0)(x-x_0)+o(x-x_0) l(x)=l(x0)+l(1)(x0)(xx0)+o(xx0)
为了得到 l l l的最小值,梯度下降法的目标是得到一个比之前的 l ( x 0 ) l(x_0) l(x0)更小的值,然后一步一步减小。为了得到x,使得 l ( x ) < l ( x 0 ) l(x)<l(x_0) l(x)<l(x0),令:
x − x 0 = − η ∗ l ( 1 ) ( x 0 ) x-x_0=-\eta *l^{(1)}(x_0) xx0=ηl(1)(x0)
其中 η \eta η为一用于缩放的正常数,此时:
l ( x ) ≈ l ( x 0 ) + l ( 1 ) ( x 0 ) ( x − x 0 ) = l ( x 0 ) − η ∗ l ( 1 ) ( x 0 ) 2 < l ( x 0 ) l(x) \approx l(x_0)+l^{(1)}(x_0)(x-x_0)=l(x_0)-\eta *{l^{(1)}(x_0)}^2<l(x_0) l(x)l(x0)+l(1)(x0)(xx0)=l(x0)ηl(1)(x0)2<l(x0)
基于一阶泰勒展开的梯度下降,目标是求得当前函数在给定 x 0 x_0 x0的一个小范围内的更小值。

基于二阶泰勒展开的梯度下降

l ( x ) = l ( x 0 ) + l ( 1 ) ( x 0 ) ( x − x 0 ) + l ( 2 ) ( x 0 ) 2 ( x − x 0 ) 2 + o ( ( x − x 0 ) 2 ) l(x)=l(x_0)+l^{(1)}(x_0)(x-x_0)+{l^{(2)}(x_0) \over 2}(x-x_0)^2+o((x-x_0)^2) l(x)=l(x0)+l(1)(x0)(xx0)+2l(2)(x0)(xx0)2+o((xx0)2)

l ( x ) ≈ l ( x 0 ) + l ( 1 ) ( x 0 ) ( x − x 0 ) + l ( 2 ) ( x 0 ) 2 ( x − x 0 ) 2 = l ( 2 ) ( x 0 ) 2 ( x − x 0 + l ( 1 ) ( x 0 ) l ( 2 ) ( x 0 ) ) 2 + c o n s t a n t l(x) \approx l(x_0)+l^{(1)}(x_0)(x-x_0)+{l^{(2)}(x_0) \over 2}(x-x_0)^2 = {l^{(2)}(x_0) \over 2}(x-x_0+{l^{(1)}(x_0) \over l^{(2)}(x_0)})^2+constant l(x)l(x0)+l(1)(x0)(xx0)+2l(2)(x0)(xx0)2=2l(2)(x0)(xx0+l(2)(x0)l(1)(x0))2+constant
x = x 0 − l ( 1 ) ( x 0 ) l ( 2 ) ( x 0 ) x=x_0-{l^{(1)}(x_0) \over l^{(2)}(x_0)} x=x0l(2)(x0)l(1)(x0) , l ( x ) l(x) l(x)得到 x 0 x_0 x0小范围内的最小值。

附录二 数值稳定性

对于使用sigmoid或者softmax函数做分类问题时,在使用梯度下降算法时,为了数值稳定性,在计算梯度的时候,将softmax/sigmoid+loss作为一层来对待。pluskid的Softmax vs. Softmax-Loss: Numerical Stability详细解释了其中原因。

参考文献

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值