LightGBM和XGBoost都是GBDT的高效实现,所以先简单介绍下GBDT。
1. Gradient Boosting Decision Tree
提升树的学习优化过程中,损失函数平方损失和指数损失时候,每一步优化相对简单,但对于一般损失函数优化的问题,Freidman提出了Gradient Boosting算法,其利用了损失函数的负梯度在当前模型的值
−[∂f(xi)∂L(y,f(xi))]f(x)=fm−1(x)
作为回归问题提升树算法的残差近似值,去拟合一个回归树。
1.1 函数空间的数值优化
优化目标是使得损失函数最小,(N是样本集合大小):
F∗(x)=ρargmini=1∑NL(yi,ρ)
GBDT是一个加法模型:fm(x)是每一次迭代学习的到树模型。
F^(x)=FM(x)=m=1∑Mfm(x)
对于其每一步迭代:
fm(x)=−ρmgm(x)
其中
gm(x)=[∂F(x)∂ϕ(F(x))]F(x)=Fm−1(x)ϕ(F(x))=Ey[L(y,F(x))∣x],Fm−1(x)=i=0∑m−1fi(x)
其实L(y,F(x))就是损失函数,ϕ(F(x))是当前x下的损失期望,gm(x)是当前x下的函数梯度。最终fm(x)学习的是损失函数在函数空间上的负梯度。
对于权重ρm通过线性搜索求解(这也是后面算法改进的点):
ρm=argρminEy,xL(y,Fm−1(x)−ρ∗gm(x))
理解:每一次迭代可以看做是采用梯度下降法对最优分类器F∗(x)的逐渐比较,每一次学习的模型fm(x)是梯度,进过M步迭代之后,最后加出来的模型就是最优分类器的一个逼近模型,所以fm(xi)使用单步修正方向−gm(xi):
−gm(xi)=gm(x)=[∂F(x)∂L(F(x))]F(x)=Fm−1(x)
这里的梯度变量是函数,是在函数空间上求解(这也是后面XGBoost改进的点),注意以往算法梯度下降是在N维的参数空间的负梯度方向,变量是参数。这里的变量是函数,更新函数通过当前函数的负梯度方向来修正模型,是它更优,最后累加的模型近似最优函数。
1.2算法描述
输入:训练数据集T={(x1,y1),(x2,y2),⋅⋅⋅,(xN,yN)},$ x_i \in \chi = R^n, y_i \in \gamma={-1,+1}, \ i=1,2,···,N $;
输出:回归树fM(x)
-
初始化
f0(x)=argcmini=1∑NL(yi,c)
-
对m=1,2,…M
-
对i=1,2,…,N,计算
rmi=−[∂f(xi)∂L(y,f(xi))]f(x)=fm−1(x)
-
对rmi拟合一颗回归树,得到第m棵树的叶结点区域Rmj, j=1,2,...J,即一棵由J个叶子节点组成的树。
-
对j=1,2,...J,计算
cmj=argcminxi∈Rmj∑L(yi,fm−1(xi)+c)
2.2,2.3这一步相当于回归树递归在遍历所有切分变量j和切分点s找到最优j,s,然后在每个节点区域求最优的c。参考回归树生成算法
-
更新fm(x)=fm−1(x)+j=1∑JcmjI(x∈Rmj)
-
得到回归树
f^(x)=fM(x)=m=1∑Mfm(x)=m=1∑Mj=1∑JcmjI(x∈Rmj)
在回归树生成时,建树选择分裂点必须要遍历所有数据在每个特征的每个切分点的值,如果是连续特征就计算复杂度非常大,也是GBDT训练主要耗时所在。所以在这一点也是XGBoost和LightGBM改进的地方。
具体算法算理:GBDT原理-Gradient Boosting Decision Tree
2 XGBoost原理
XGBoost是GBDT的改进和重要实现,主要在于:
- 提出稀疏感知(sparsity-aware)算法。
- 加权分位数快速近似数学习算法。
- 缓存访问模式,数据压缩和分片上的实现上的改进。
- 加入了Shrinkage和列采样,一定程度上防止过拟合。
2.1 Tree Boosting
首先XGBoost也是一个加法模型,首先其在目标函数中加入了正则化项:
L(ϕ)=i∑ℓ(y^i,yi)+k∑Ω(fk)Ω(f)=γT+21λ∥w∥2(2)
泰勒级数∑n=0∞n!f(n)(a)(x−a)a
方程2不能再欧式空间上用传统方法优化,而是通过迭代获得最优解。y^i(t)是第i个实例在第t次迭代的预测值,需要加入ft来最小化以下目标
L(ϕ)=i∑ℓ(yi,y^i(t−1)+ft(Xi))+k∑Ω(fk)
通过泰勒二阶展开近似来快速优化目标函数(泰勒级数∑n=0∞n!f(n)(a)(x−a)a)):
L(ϕ)≃i∑[ℓ(yi,y^i(t−1))+gift(Xi)+21hift2(xi)]+k∑Ω(fk)
其中,gi=∂yt−1l(yi,y^t−1),hi=∂yt−12l(yi,y^t−1)即l的一阶和二阶导数。移除常数项得到:
L~(ϕ)=i∑[gift(Xi)+21hift2(xi)]+k∑Ω(fk)(3)
定义Ij={i∣q(xi)=j}作为叶子结点j的实例集合。将方程3展开为:
L~(ϕ)=i∑[gift(Xi)+21hift2(xi)]+γT+21λj=1∑Twj2=j=1∑T[(i∈Ij∑gi)wj+21(i∈Ij∑hi+λ)wj2]+γT(4)
计算权重公式:
wj∗=−∑i∈Ijhi+λ∑i∈ijgi(5)
带入方程4目标函数得(一阶和二阶导数合并成了一项):
L~(t)(q)=−21j=1∑T∑i∈Ijhi+λ(∑i∈Ijgi)2+γT(6)
这一项算出的值就是第t棵树要优化目标函数,使其尽量小。下图展示计算过程(图中Obj少了一个-1/2,我就是这么较真),目标函数越小越好。

枚举所有可能结构的树是不可能的,通过贪心算法从叶节点开始迭代得添加分支,IL,IR分别是分割点左右分支的实例集,分割的损失下降定义为:
L=21[∑i∈ILhi+λ(∑i∈Igi)2+∑i∈IRhi+λ(∑i∈Igi)2−∑i∈Ihi+λ(∑i∈Igi)2]−λ(7)
为什么是这个呢,很简单,就是方程6在分割前后的差值。
2.2 Weighted Quantile Sketch-加权分位
近似算法通过特征百分位点作为划分候选。使集合Dk={(x1k,h1),(x2k,h2),...(xnk,hn)}代表样本点的第k个特征值和二阶导数。定义排序函数:
rk(z)=∑(x,h)∈Dkh1(x,h)∈Dk,x<z∑h(8)
方程8表示特征值小于z的样本占整体的比例。目标是找到候选切分点{sk1,sk2,...skl,}使得:
∣rk(sk,j)−rk(sk,j+1)∣<ϵ,sk1=iminxik,skl=imaxxik(9)
其中ϵ是近似因子,这意味着有1/ϵ个候选点,每个数据点权重是hi,方程3说明为什么用它做权重。
i=1∑n21hi(ft(xi)−gi/hi)2+Ω(ft)+constant,
其中hi即为平方损失的权重,对于大数据集,找到满足条件的候选分裂是非常重要的。以前的分位算法中没有权重,因为加权数据集没有分位数。
为了解决这个问题,XGBoost提出了新颖的分布式加权的分位数算法,作者理论证明它可以处理加权的数据。总的思路是提出一个支持合并和修剪操作的数据结构,每个操作都被证明保持一定的准确性水平。 证明见xgboost-supp.pdf。
2.3 Sparsity-aware Split Finding
真实数据很多都是稀疏的数据,有很多原因:1.数据中有缺失值。2.统计中频繁出现0条目。3.人工特征工程造成,例如one-hot。为了算法稀疏感知,XGBoost每个树节点加入了默认方向,如图:

当数据值缺失的时候,样本被划分到默认方向,默认方向是通过学习数据获得的,其算法如下图Alg.3,关键提升在于只看不缺失的实例进入Ik,所提出的算法将不存在作为缺失值处理,并学习处理缺失值的最佳方向。 通过将枚举限制为恒定的解决方案,当不存在对应于用户指定的值时,也可以应用相同的算法。

大多数现有的树学习算法或者只是针对密集数据进行优化,或者需要特定的程序来处理有限的情况,如分类编码。 XGBoost以统一的方式处理所有的稀疏模式。 更重要的是,作者的方法利用稀疏性使计算复杂度与输入中非缺失条目的数量成线性关系。 图5显示了稀疏感知和对Allstate-10K数据集(的简单实现的比较。 作者发现稀疏感知算法的运行速度比原始版本快50倍。 这证实了稀疏感知算法的重要性。

具体算法原理见:XGBoost原理-XGBoost A Scalable Tree Boosting System
3 lightGBM
LightGBM提出两种新方法:Gradient-based One-Side Sampling (GOSS) 和Exclusive Feature Bundling (EFB)(基于梯度的one-side采样和互斥的特征捆绑)
3.1 Gradient-based One-Side Sampling
针对数量大,GOSS保留所有的梯度较大的实例,在梯度小的实例上使用随机采样。为了抵消对数据分布的影响,计算信息增益的时候,GOSS对小梯度的数据引入常量乘数。GOSS首先根据数据的梯度绝对值排序,选取top a个实例。然后在剩余的数据中随机采样b个实例。接着计算信息增益时为采样出的小梯度数据乘以(1-a)/b,这样算法就会更关注训练不足的实例,而不会过多改变原数据集的分布。
在GOSS中,
- 首先根据数据的梯度将训练降序排序。
- 保留top a个数据实例,作为数据子集A。
- 对于剩下的数据的实例,随机采样获得大小为b的数据子集B。
- 最后我们通过以下方程估计信息增益:
V~j(d)=n1(njl(d)(∑xi∈A:xij≤dgi+b1−a∑xi∈B:xij≤dgi)2+nrj(d)(∑xi∈A:xij>dgi+b1−a∑xi∈B:xij>dgi)2)(1)
此处GOSS通过较小的数据集估计信息增益V~j(d),将大大地减小计算量。更重要的的,理论表明GOSS不会丢失许多训练精度。
3.2 Exclusive Feature Bundling
针对特征维度高,而高维的数据通常是稀疏的,能否设计一种无损地方法来减少特征的维度。特别的,稀疏特征空间中,许多特征是互斥的,例如他们从不同时为非零值。我们可以绑定互斥的特征为单一特征,通过仔细设计特征臊面算法,作者从特征捆绑中构建了与单个特征相同的特征直方图。这种方式的间直方图时间复杂度从O(#data * #feature)降到O(#data * #bundle),由于#bundle << # feature,我们能够极大地加速GBDT的训练过程而且损失精度。
有两个问题:
- 怎么判定那些特征应该绑在一起(build bundled)?
- 怎么把特征绑为一个(merge feature)?
3.2.1 bundle(什么样的特征被绑定)?
**理论 4.1:**将特征分割为较小量的互斥特征群是NP难的。
证明:将图着色问题归约为此问题,而图着色是NP难的,所以此问题就是NP难的。
给定图着色实例G=(V, E)。以G的关联矩阵的每一行为特征,得到我们问题的一个实例有|V|个特征。 很容易看到,在我们的问题中,一个独特的特征包与一组具有相同颜色的顶点相对应,反之亦然。
算法:基于上面的讨论,设计了算法3,伪代码见下图,具体算法:
- 建立一个图,每个边有权重,其权重和特征之间总体冲突相关。
- 按照降序排列图中的度数来排序特征。
- 检查每个排序之后的每个特征,这个特征绑定到使得冲突最小的绑定,或者建立一个新的绑定。
为了继续提高效率,LightGBM提出了一个更加高效的无图的排序策略:将特征按照非零值个数排序,这和使用图节点的度排序相似,因为更多的非零值通常会导致冲突,新算法在算法3基础上改变了排序策略。

3.2.2 merging features(特征合并)
通过将互斥特征放在不同的箱中来构建bundle。这可以通过将偏移量添加到特征原始值中实现,例如,假设bundle中有两个特征,原始特征A取值[0, 10],B取值[0, 20]。我们添加偏移量10到B中,因此B取值[10, 30]。通过这种做法,就可以安全地将A、B特征合并,使用一个取值[0, 30]的特征取代AB。算法见上图算法4。
EFB算法能够将许多互斥的特征变为低维稠密的特征,就能够有效的避免不必要0值特征的计算。实际,通过用表记录数据中的非零值,来忽略零值特征,达到优化基础的直方图算法。通过扫描表中的数据,建直方图的时间复杂度将从O(#data)降到O(#non_zero_data)。
****原文:https://blog.****.net/shine19930820/article/details/79274875
LightGBM原理-LightGBM: A Highly Efficient Gradient Boosting Decision Tree
Reference
- GBDT原理-Gradient Boosting Decision Tree
- XGBoost原理-XGBoost A Scalable Tree Boosting System
- LightGBM原理-LightGBM: A Highly Efficient Gradient Boosting Decision Tree