1、概述
LightGBM是微软于2017年提出的boosting框架,其基本原理与XGBoost一样,使用基于学习算法的决策树,只是在框架上做了一优化(重点在模型的训练速度的优化)。我在参加 Kaggle 比赛的过程中发现,除了 XGBoost,表现较好的且使用较为广泛的 GBM 模型就是 LightGBM 。因此我认为大概了解背后的原理是必要的。
在论文摘要中作者提到,GBDT 是一种非常流行的机器学习算法,有很多有效的实现,虽然在这些实现中采用了许多工程优化方法,但在特征维数高、数据量大的情况下,其效率和可扩展性仍不能令人满意。一个主要的原因是,对于每个特征,需要扫描所有的数据实例来估计所有可能的分割点的信息增益,这是非常耗时的。
为了解决这个问题,作者提出了两种新的技术:
- 1、GOSS(Gradient based One Side Sampling):移除梯度较小的数据实例,只使用其余的数据估计信息增益。由于梯度较大的数据实例在信息增益的计算中起着更重要的作用,所以GOSS可以在较小的数据量下获得相当准确的信息增益估计。
- 2、EFB(Exclusive Feature Bundling):bundle 不会同时为零的特征(互斥),达到减少特征数量的目的。寻找互斥特征的最优 bundle 是 NP-Hard 的,但是贪心算法可以获得很好的近似比(因此可以有效地减少特征的数量,而不会对分割点的确定造成很大的影响)。
在多个公共数据集上的实验表明,LightGBM 可以将传统 GBDT 的训练速度提高20倍以上,同时达到几乎相同的精度。
2、LightGBM 轻量级提升学习方法
2.1、基于直方图的排序算法
传统的 GDBT 方法的主要计算开销是各 Decision Tree 的学习过程,而学习过程的主要开销是最优划分点的寻找。
最流行的方法是 Pre-sorted 方法,也就是预先将所有特征进行排序,然后对所有数据,遍历所有可能的划分点,这样就可以找到最优划分点。但是这种算法的计算开销和空间占用都很大。
另一种算法便是基于直方图的算法。该算法将连续的特征值进行离散化分桶,然后用桶中的特征值数量来构建直方图。然后根据直方图的离散值,遍历寻找最优的分割点。相比 Pre-sorted 算法,基于直方图的算法在时间和空间开销上都较小。
算法流程如下:
看起来很复杂的样子,拆解开来实际上就是:设置一个最大深度,然后遍历每一层,在每一层中遍历各个叶子节点,然后对每个结点中的数据,遍历所有特征,根据当前特征的分桶规则将当前结点中的所有数据进行分桶,并实时更新各桶中的数据量以及梯度之和,以供后续寻找最优划分点使用。
想象这样一个例子,某个结点上的数据点为,也就是说在第一维特征上,前两个样本点是属于 bin1 的,后两个样本点是属于 bin 2 的,在第二维特征上,而第二和第三个样本点是属于 bin 1 的,第一和第四个样本点是属于 bin 2 的,现在这个结点保存了两个直方图(对于两个维度),而我们需要考虑两个划分点(即第一维上 bin 1和 bin 2中间的划分点以及第二维上 bin 1和 bin 2中间的划分点),假设按第一维来划分增益较多,则我们将结点划分为和两个子结点,此时产生左结点的两个直方图,第一维特征的直方图很简单,只需要将 bin 2 的部分清零即可,第二维的直方图则需要根据结点中样本的第二维特征(实际上第二维特征就等于其在第二维上所属的 bin 的序号)进行更新,实际上就是按照上图所示的算法建立直方图,然后右结点的两个直方图可由父亲结点和左子结点做差得出。
不难看出,上述算法中,建立直方图的计算复杂度是,通过直方图找到最佳划分点的复杂度为。由于通常比大得多,因此总的复杂度是量级的。也就是说,想降低复杂度,要减少所用的数据量或者所用特征数量。
相比之下,Pre-sorted 算法寻找最优划分的复杂度为。也就是说,直方图算法减小了寻找最优划分点的计算开销。
实际上,基于直方图的算法还可以进一步节约计算开销,LightGBM 的直方图可以做差加速。所谓做差加速,即一个叶子的直方图可以由它的父亲结点的直方图与它兄弟的直方图做差得到。构造的直方图本来需要遍历该叶子结点上所有数据,但是直方图做差仅需遍历直方图的个桶即可(即直方图区间),速度上可以提升一倍。
此外,直方图算法不仅不需要额外存储预排序的结果,而且可以只保存特征离散化后的值,而这个值一般用 8 位整型存储就足够了,内存消耗可以降低为原来的。
基于直方图的算法的时间复杂度为,为了进一步提高算法的运行效率。需要减少所需的样本数量或者特征数量,而 LightGBM 提出的 GOSS 和 EFB 就是用来做这两件事的。接下来我们看一下这两个算法的具体流程和原理。
2.2、GOSS采样策略
既然要对样本进行采样,就要树立规则来判断各样本对模型的重要程度,或者说对损失函数的贡献程度。一种隐形的采样方法在 AdaBoost 中有所运用,即通过给样本赋予不同的权重来表示其重要性,权重大的样本会在分类器的训练过程中得到重点关注。
作者提出了类似的权重概念,来定义样本的重要性。样本的梯度越小,则样本的训练误差越小,表示样本训练得越好,其对于模型表现的提高的重要性就越小,因此赋予较小的权重,而大梯度的样本则赋予较大权重。
要想减少样本数量,我们只需要移除梯度较小的这部分样本即可。但此时会产生一个问题,那就是破坏原始的数据分布。
为解决这个问题,lightGBM 采用了 one-side 采样的方式来适配:保留所有的大梯度样本,对小梯度样本进行随机采样(只对小梯度样本采样,因此名为 one-side),同时为了保证分布的一致性,在计算信息增益的时候,将采样的小梯度样本乘以一个常量:,这里表示大梯度样本采样比例,表示小梯度样本的采样比例(这里的百分比都是相对于全部样本而言的)。
举例来说,100个样本中,大梯度样本有 20 个,小梯度样本有 80 个,小梯度样本量是大梯度样本数据量的 4 倍,则大样本采样比率 等于 0.2,假设小梯度样本的采样率为 40%,则 等于 0.4,小梯度样本的采样数目等于 0.4 ×100 = 40 个,为了保证采样前后样本的分布保持一致,最后小梯度样本采样得到的数据在计算信息增益时需要乘以。
整个算法流程如图所示:
接下来文章进一步给出了 GOSS 的理论证明,说明了:
(1)GOSS 采样可以得到和使用全部数据差不多的结果。
(2)GOSS 的泛化性能可能更好,因为采样过程起到了防止过拟合的作用。
2.3、EFB特征合并
高维数据通常是非常稀疏的,而且很多特征是互斥的(即两个或多个特征列不会同时为0),lightGBM 对这类数据采用了 EFB(exclusive feature bundling)的优化策略,将这些互斥特征分组合并为个维度。通过这种方式,将特征的维度降下来。
算法要解决的问题有两个:
- 1、哪些特征可以 bundle 在一起;
- 2、如何构建 bundle,实现特征降维。
对于第一个问题,作者说明了将特征划分为最少数量的互斥特征 bundle 本质上属于 NP-Hard 问题。因为我们可以由图着色问题(Graph Coloring Problem)归约到此问题。
图着色问题就是给定一张图,用最少种类的颜色对图进行着色,使得任意相邻的两个顶点颜色不同。
创建一个图,令图中的节点表示特征,将不互斥的特征用一条边连接起来,边的权重就是两个相连接的特征的总冲突值,这样一来,需要绑定的特征就是在图着色问题中要涂上同一种颜色的那些点(特征)。
即然此问题是 NP-Hard 的,那么我们就找不到多项式的算法来得到精确解,因此论文中给出了一种贪心算法:
简单来说,算法流程如下:
1、创建图,令图中的节点表示特征,边权为特征间的冲突数。
2、将特征按照在图中的度进行降序排序。
3、遍历排序后的特征,对每个特征,遍历现有的 bundle,若将当前特征加入当前 bundle 中后 bundle 的总冲突数不超过阈值 ,则加入,否则检查下一个 bundle,若现有 bundle 均不满足条件,则新开一个 bundle 并将当前特征放入其中。
采用这种方法对于特征数目不大的数据性能还不错,但是对于超大规模的特征将会出现性能瓶颈。一个优化的方向就是:按照非零值的个数进行排序,通常非零值越多冲突就越大,我们就把它排得更靠前。
对于第二个问题:应该如何如何构建bundle?关键在于构建前的特征的值在构建后的 bundle 中依然能够被识别。
由于基于直方图的方法存储的是离散的 bin 而不是连续的数值,因此我们将不同特征的 bin 值设定为不同的区间即可。例如,特征 A 的 bin 值为 [0,10),特征 B 的 bin 值为 [0,20),要想将两个特征 bin 合并,我们可以将特征 B 的特征 bin 的值加上10,其取值区间将变为 [10,30)。之后,将特征 A 和 B 合并,使用范围 [0,30] 的 bundle 来代替原来的特征 A 和 B 即可。
算法流程如下:
下面举例说明上述算法流程,设 bundle 中有 2 个特征,的 bin 为 和 ,的 bin 为 和 ,则第一个循环结束后,我们可以得到。现在假设我们有一个数据 ,其原来的 bin 值为 ,即 落在第二个 bin 中, 落在第一个 bin 中,经过第二个循环后,其 bin 值更新为 ,即 。
有了 EFB 方法,数据的 shape 就可以由原来的 缩小为现在的 ,且。可以看到,EFB 方法降低了数据特征规模,提高了模型的训练速度。
2.4、Leaf-wise (Best-first) Tree Growth
在树的生成方式上,lightGBM 与 XGBoost 有所区别。
XGBoost 决策树的生长策略是 level-wise,即逐层对各层的每个结点进行划分,直至达到终止条件。它不加区分的对待同一层的叶子,带来了很多没必要的开销,因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。
lightGBM 决策树的生长策略是 leaf-wise。与 level-wise 不同,leaf-wise 策略以降低模型损失最大化为目的,对当前叶子中切分增益最大的叶子进行切分。这种方法可以降低更多的误差,得到更好的精度,但缺点是可能会长出比较深的决策树,产生过拟合。因此 LightGBM 在 leaf-wise 之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。
2.5、直接支持类别特征(即不需要做 one-hot 编码)
大多数机器学习工具都无法直接支持类别特征,一般需要把类别特征,转化到多维的 one-hot 编码特征,降低了空间和时间的效率。而类别特征的使用是在实践中很常用的。基于这个考虑,LightGBM 优化了对类别特征的支持,可以直接输入类别特征,不需要额外的 one-hot 编码展开。并在决策树算法上增加了类别特征的决策规则。
2.6、直接支持高效并行
LightGBM 还具有支持高效并行的优点。LightGBM 原生支持并行学习,目前支持特征并行和数据并行的两种。
- 1、特征并行的主要思想是在不同机器在不同的特征集合上分别寻找最优的分割点,然后在机器间同步最优的分割点。
- 2、数据并行则是让不同的机器先在本地构造直方图,然后进行全局的合并,最后在合并的直方图上面寻找最优分割点。
LightGBM 针对这两种并行方法都做了优化,在特征并行算法中,通过在本地保存全部数据避免对数据切分结果的通信;在数据并行中使用分散规约 (Reduce scatter)把直方图合并的任务分摊到不同的机器,降低通信和计算,并利用直方图做差,进一步减少了一半的通信量。
Reference:
https://fuhailin.github.io/LightGBM/