我在学习lightGBM的时候苦于找不到质量高的学习资料,后来突然想起最好的资料难道不就是作者的原论文吗?所以本文主要是对LightGBM原论文的阅读翻译,一方面督促自己把论文精度一遍,一方面分享给有需要的朋友。
参考资料:
原文:LightGBM: A Highly Efficient Gradient Boosting Decision Tree
————————————————————————————————————————————
摘要
梯度提升树(Gradient Boosting Decision Tree,GBDT)是一种非常流行的机器学习算法,并且有很多有效的实现,如XGBoost和pGBT。尽管在这些实现中已经采用了很多工程优化的手段,但是当特征维度高、数据量大时,其效率和可扩展性仍然不能令人满意。主要的原因是,对于每个特征,需要扫描所有数据点,计算所有可能的分割节点的信息增益,这非常耗时。为了解决这个问题,我们提出了两种新技术:基于梯度的单侧采样(Gradient-based One-Side Sampling ,GOSS)和互斥特征捆绑(Exclusive Feature Bundling ,EFB)。在GOSS方法中,我们显著减少了梯度小的数据点的比例,仅使用剩下的数据来计算信息增益。我们证明,具有较大梯度的数据在信息增益的计算中起着更重要的作用,因此利用GOSS方法计算得到的信息增益即使只用了较少数据,精度也非常高 。在EFB方法中,我们捆绑互斥的特征(即,它们很少同时取非零值)去减少特征数量。我们证明找到最理想的特征捆绑的解法是NP难的,但是贪心算法可以达到近似效果(这样可以有效地减少特征的数量又不会大大降低分割节点最终的准确性)。利用GOSS和EFB方法对GBDT的新的优化实现,我们叫它lightGBM。我们针对多个公开数据集做了实验,实验表明LightGBM可以使传统GBDT的训练过程加速20倍以上,同时实现几乎相同的精度。
1 Introduction
梯度提升树(GBDT)由于其效率高,准确性高和可解释性强被广泛使用。 GBDT在许多机器学习任务中表现非常好,例如多分类问题,点击率预测和排序学习。 近年来,随着大数据的出现(在特征和数据量方面),GBDT面临着新的挑战,特别是在准确性和效率之间的权衡。 对于每个特征,常规的GBDT需要扫描所有数据样本以估计所有可能的分割节点的信息增益。 因此,计算的复杂性与特征维度和数据量成比例。 这使得在处理大数据时非常耗时。
为了应对这一挑战,最直截了当的办法是减少数据量、缩小特征维度。 然而,这个想法是非常有价值的。 例如,目前还不清楚如何为GBDT进行数据采样。 虽然有些研究根据数据权重对数据进行采样进而加速的训练过程,但由于GBDT中根本没有样本权重,因此无法直接应用于GBDT。 在本文中,我们提出了两种新的技术来实现这一目的,下面详细叙述。
基于梯度的单侧采样(GOSS)。 虽然GBDT中的数据样本没有初始权重,但我们注意到不同梯度的数据样本在信息增益的计算中起着不同的作用。根据信息增益的定义,具有较大梯度的那些数据(即训练不足的实例)将对信息增益做出更多贡献。 因此,当对数据样本进行降采样时,为了保持信息增益计算的准确性,我们应该更好地保持那些具有大梯度(例如,大于预定阈值,或者在最高百分位数之间)的样本,仅随机删除那些梯度小的样本。 我们证明,在相同的采样率下,这种处理方法最终计算出的信息增益比均匀随机采样要准确,特别是当信息增益的值具有大范围时。
互斥特征捆绑(EFB)。 在实际应用中,通常是特征维度大但特征空间非常稀疏,这给我们提供了设计出一种几乎无损失的减少有效特征数量的方法的可能性。具体地说,在稀疏特征空间中,许多特征(几乎)是互斥的,即它们很少同时取非零值。 示例包括单热特征(例如,文本挖掘中的独热编码)。 我们可以放心地捆绑这些互斥特征。 为此,我们通过将最佳捆绑问题减少到图着色问题来设计一种有效的算法(通过将特征作为顶点并为每两个特征添加边缘,如果它们不相互排斥),并通过贪婪算法解决它。 恒定近似比。
我们称新的搭配GOSS和EFB算法的GBDT叫LightGBM。我们在多个公开数据集上的实验表明,LightGBM将训练速度加速了近20倍,同时能达到几乎相同的精度。
本文的其余部分整理如下。首先,我们在第2部分检查整理了GBDT算法及其相关工作。然后,我们在第3、4部分介绍了GOSS算法和EFB算法的细节。第5部分呈现了在公开数据集上的实验结果。最后,第6部分是结论。
2 Preliminaries
2.1 GBDT and Its Complexity Analysis
GBDT是一种集成模型,以决策树为基学习器,按顺序迭代训练。在每次迭代中,GBDT通过拟合负梯度(也称为残差)来学习决策树。
GBDT的主要成本在于学习决策树,而决策树的学习中最耗时的部分是寻找最佳分割点。最常用的寻找分割点的算法是预排序算法,它将特征取值预先排序并枚举出所有可能的分割点。该算法简单易行,能找到最优分割点,但在训练速度和内存消耗方面都是低效的。另一种流行的算法是基于直方图的算法,如Alg.1所示。基于直方图的算法在训练中将连续的特征分箱处理成离散值,利用这些离散的箱子构建特征直方图。由于基于直方图的算法在内存消耗和训练速度上都更有效,因此我们将在其基础上开展我们的工作。
如Alg.1,直方图算法基于特征的直方图找最佳分割点。构建直方图的复杂度为O(#data × #feature),O(#bin × #feature)。通常箱子长度比数据量小得多,所以直方图的构建导致主要的复杂度。如果我们可以减少数据量或特征维度,我们将能够大大加快GBDT的训练过程。
2.2 Related Work
在文献中已经有很多关于GBDT的实现,包括XGBoost、pGBRT、scikit-learn和R中的GBM。R中的scikit-learn和gbm实现了预排序算法,PGBRT实现了基于直方图的算法。XGBoot同时支持预排序算法和基于直方图的算法。文献「3」中指出,XGBoost优于其他工具。因此,我们在实验部分使用XGBoost作为我们的基线。
为了减少训练数据的大小,一种常见的方法是对数据降采样。例如,在文献「5」中,如果数据样本的权重小于固定阈值,则对数据样本进行过滤。SGB在每次迭代中使用随机子集来训练弱学习器。在文献「6」中,在训练过程中动态调整采样率。然而,除了SGB以外的所有这些工作都是基于AdaBoost的,并且不能直接应用于GBDT,因为在GBDT中样本没有初始权重。虽然SGB可以应用于GBDT,但通常会影响精度,因此不是一个理想的选择。
类似地,为了减少特征维度,过滤弱特征是很自然的想法。这通常是通过主成分分析或投影寻踪来实现的。然而,这些方法高度依赖于特征显著冗余的假设,这在实践中可能并不总是正确的(特征被设计出来通常会有自己独特的作用,去除它们中的任何一种可能在某种程度上影响训练精度)。
实际应用中的大规模数据集通常非常稀疏。使用预排序算法的GBDT可以通过忽略具有零值的特征来降低训练成本。然而,基于直方图的算法的GBDT针对稀疏问题不具有有效的优化解。原因在于基于直方图的算法对于每个数据样本,无论特征值是否为零,都需要去检索特征直方图的值。最好是基于直方图的算法的GBDT也可以有效地利用这种稀疏性质。
为了解决前人研究中的局限性,我们提出了两种新技术,称为基于梯度的单侧采样(GOSS)和互斥特征捆绑(EFB)。更多细节将在下一节中介绍。
这里我来简单阐述一下作者所说的直方图算法。这算法其实很简单,和XGBoost中分割点的近似算法有点像,只不过XGBoost中是利用百分位数来粗略的卡分割位置,而直方图算法是直接把特征值进行分箱然后编号。箱子的长度是可以设定的,直方图算法就是把多个点放到一个箱子里算成一个点了,这样找分割位置的时候,原来预排序算法一步走一个点,现在一步走一个箱子,肯定是快了不少,内存消耗也会变小。
作者原文中说的特征为稀疏矩阵的情况,预排序可以忽略为0的,这就相当于数据量急剧减小。但直方图算法有个装箱的过程,无论是是不是0你都得首先装箱,这就是作者说的此时效率低的原因。
除此之外直方图算法还有一个做差加速的操作,听起来名字高大上,其实很弱智。这个操作是说一个节点的直方图可以用它的父母节点的直方图减去兄弟节点的直方图得到,这是显而易见的。
3 Gradient-based One-Side Sampling
在这一节中,我们提出了一种新的GBDT采样方法,可以在减少数据数量和保持决策树的精度之间实现良好的平衡。
3.1 Algorithm Description
在AdaBoost中,样本权重能良好的表现数据的重要性。然而,在GBDT中,没有初始样本权重,因此对于AdaBoost提出的抽样方法不能直接应用。幸运的是,我们注意到GBDT中每个数据样本的梯度蕴含的信息为数据采样提供了启发。具体来说,如果一个样本的梯度取值很小,那么这个样本的训练误差也很小,表示它已经被良好地训练。一个简单的想法是丢弃这些小梯度的数据样本。然而,这样做会改变数据分布,这将损害模型学习的准确性。为了避免这个问题,我们提出了一种新的方法,称为基于梯度的单侧采样(GOSS)。
GOSS方法保留所有较大梯度的样本,并对剩下小梯度样本进行随机采样。为了补偿对数据分布的影响,在计算信息增益时令小梯度数据样本乘以一个常数(见Alg.2)。具体来说,GOSS算法首先根据数据梯度的绝对值进行排序,排序后选择前 a × 100 % a×100\% a×100%的样本(这里就是筛选大梯度数据卡的阈值)。然后从剩下的数据中随机抽取 b × 100 % b×100\% b×100%的样本。之后在计算信息增益时,通过一个常数 1 − a b \frac{1-a}{b} b1−a来增大小梯度样本的权重。这样做我们就可以在不改变数据分布的同时把更多精力放在训练的没那么好的数据上。
3.2 Theoretical Analysis
GBDT使用决策树来学习出一个从输入空间 X s X^s Xs到梯度空间 G G G的映射函数。假设我们有一个数据量为 n n n的训练集 { x 1 , . . . , x n } \{x_1,...,x_n\} { x1,...,xn},其中每个 X i X_i Xi是空间 X S X^S XS中一个维度 s s s的向量。在每一次梯度提升迭代中,损失函数负梯度在当前模型输出的值表示为 { G 1 , ⋅ ⋅ ⋅ , G N } \{G_1,···,G_N\} { G1,⋅⋅⋅,GN}。决策树模型信息量最大的特征处进行分割(信息增益最大)。对于GBDT,信息增益通常是通过分裂后的方差来度量的,其定义如下。
Definition 3.1设 O O O为决策树一个固定节点内的数据集。此节点处特征 j j j在 d d d分割点的方差增益定义为:
V j ∣ O ( d ) = 1 n O ( ( ∑ { x i ∈ O : x i j ≤ d } g i ) 2 n l ∣ O j ( d ) + ( ∑ { x i ∈ O : x i j > d } g i ) 2 n r ∣ O j ( d ) ) V_{j|O}(d)=\frac{1}{n_{O}}\left(\frac{\left(\sum_{\left\{x_{i} \in O : x_{i j} \leq d\right\}} g_{i}\right)^{2}}{n_{l|O}^{j}(d)}+\frac{\left(\sum_{\left\{x_{i} \in O : x_{i j}>d\right\}} g_{i}\right)^{2}}{n_{r|O}^{j}(d)}\right) Vj∣O(d)=nO1⎝⎜⎛nl∣Oj(d)(∑{
xi∈O:xij≤d}gi)2+nr∣Oj(d)(∑{
xi∈O:xij>d}gi)2⎠⎟⎞ where n O = ∑ I [ x i ∈ O ] , n l ∣ O j ( d ) = ∑ I [ x i ∈ O : x i j ≤ d ] and n r ∣ O j ( d ) = ∑ I [ x i ∈ O : x i j > d ] \text { where } n_{O}=\sum I\left[x_{i} \in O\right], n_{l|O}^{j}(d)=\sum I\left[x_{i} \in O : x_{i j} \leq d\right] \text { and } n_{r|O}^{j}(d)=\sum I\left[x_{i} \in O : x_{i j}>d\right] where nO=∑I[xi∈O],nl∣Oj(d)=∑I[xi∈O:xij≤d] and nr∣Oj(d)=∑I[xi∈O:xij>d]对于特征 j j j,决策树选择的最优分割点为 d j ∗ = argmax d V j ( d ) d_{j}^{*}=\operatorname{argmax}_{d} V_{j}(d) dj∗=argmaxdVj(d),计算得到的最大增益为 V j ( d j ∗ ) V_{j}\left(d_{j}^{*}\right) Vj(dj∗)。然后按照特征 j ∗ j^* j∗在点 d j ∗ d_{j^*} dj∗处将数据划分成左右孩子节点。在我们提出的GOSS算法中,首先,我们将数据按照梯度绝对值进行降序排序;其次,我们保留前 a × 100 % a×100\% a×100%梯度绝对值较大的数据记为数据子集 A A A;之后剩下的数据记为 A c A^c Ac,包含 ( 1 − a ) × 100 % (1-a)×100\% (1−a)×100%的小梯度数据,从中随机采样 b × ∣ A c ∣ b \times\left|A^{c}\right| b×∣Ac∣记为子集 B B B。最后我们在并集 A ∪ B A \cup B A∪B上根据方差增益 V ~ j ( d ) \tilde{V}_{j}(d) V~j(d)来划分数据,
V ~ j ( d ) = 1 n ( ( ∑ x i ∈ A l g i + 1 − a b ∑ x i ∈ B l g i ) 2 n l j ( d ) + ( ∑ x i ∈ A r g i + 1 − a b ∑ x i ∈ B r g i ) 2 n r j ( d ) ) ( 1 ) \tilde{V}_{j}(d)=\frac{1}{n}\left(\frac{\left(\sum_{x_{i} \in A_{l}} g_{i}+\frac{1-a}{b} \sum_{x_{i} \in B_{l}} g_{i}\right)^{2}}{n_{l}^{j}(d)}+\frac{\left(\sum_{x_{i} \in A_{r}} g_{i}+\frac{1-a}{b} \sum_{x_{i} \in B_{r}} g_{i}\right)^{2}}{n_{r}^{j}(d)}\right) \ \ \ \ \ \ \ (1) V~j(d)=n1(nlj(d)(∑xi∈Algi+b1−a∑xi∈Blgi)2+nrj(d)(∑xi∈Argi+b1−a∑xi∈Brgi)2) (1) where A l = { x i ∈ A : x i j ≤ d } , A r = { x i ∈ A : x i j > d } , B l = { x i ∈ B : x i j ≤ d } , B r = { x i ∈ B : x i j > d } \begin{array}{l}{\text { where } A_{l}=\left\{x_{i} \in A : x_{i j} \leq d\right\}, A_{r}=\left\{x_{i} \in A : x_{i j}>d\right\}, B_{l}=\left\{x_{i} \in B : x_{i j} \leq d\right\}, B_{r}=\left\{x_{i} \in B :\right.} \\ {x_{i j}>d \}}\end{array} where Al={
xi∈A:xij≤d},Ar={
xi∈A:xij>d},Bl={
xi∈B:xij≤d},Br={
xi∈B:xij>d}系数 1 − a b \frac{1-a}{b} b1−a是为了将子集 B B B的梯度和规范回 A c A^c Ac的大小。
这样,在GOSS中,我们在一个较小的数据集上得到 V ~ j ( d ) \tilde{V}_{j}(d) V~j(d)去确定分割点,而不是从全部的数据集上计算 V j ( d ) V_j(d) Vj(d),计算成本大大减少。更重要的是,下面的定理可以证明GOSS算法并不会损失很多训练精度,同时又比单纯随机采样要好。由于篇幅的限制,我们把定理的证明留在了补充材料中。
Theorem 3.2 我们将GOSS算法中的近似误差定义为
E ( d ) = ∣ V ~ j ( d ) − V j ( d ) ∣ \mathcal{E}(d)=\left|\tilde{V}_{j}(d)-V_{j}(d)\right| E(d)=∣∣∣V~j(d)−Vj(d)∣∣∣ g ‾ l j ( d ) = ∑ x i ∈ ( A ∪ A c ) l ∣ g i ∣ n l j ( d ) \overline{g}_{l}^{j}(d)=\frac{\sum_{x_{i} \in\left(A \cup A^{c}\right)_{l}}\left|g_{i}\right|}{n_{l}^{j}(d)} glj(d)=nlj(d)∑xi∈(A∪Ac)l∣gi∣ g ‾ r j ( d ) = ∑ x i ∈ ( A ∪ A c ) r ∣ g i ∣ n r j ( d ) \overline{g}_{r}^{j}(d)=\frac{\sum_{x_{i} \in\left(A \cup A^{c}\right)_{r}}\left|g_{i}\right|}{n_{r}^{j}(d)} grj(d)=nrj(d)∑xi∈(A∪Ac)r∣gi∣因为概率至少为 1 − δ 1-\delta 1−δ,我们有
E ( d ) ≤ C a , b 2 ln 1 / δ ⋅ max { 1 n l j ( d ) , 1 n r j ( d ) } + 2 D C a , b ln 1 / δ n ( 2 ) \mathcal{E}(d) \leq C_{a, b}^{2} \ln 1 / \delta \cdot \max \left\{\frac{1}{n_{l}^{j}(d)}, \frac{1}{n_{r}^{j}(d)}\right\}+2 D C_{a, b} \sqrt{\frac{\ln 1 / \delta}{n}} \ \ \ \ \ \ (2) E(d)≤Ca,b2ln1/δ⋅max{
nlj(d)1,nrj(d)1}+2DCa,bnln1/δ (2) where C a , b = 1 − a b max x i ∈ A c ∣ g i ∣ , and D = max ( g ‾ l j ( d ) , g ‾ r j ( d ) ) \text {where } C_{a, b}=\frac{1-a}{\sqrt{b}} \max _{x_{i} \in A^{c}}\left|g_{i}\right|, \text { and } D=\max \left(\overline{g}_{l}^{j}(d), \overline{g}_{r}^{j}(d)\right) where Ca,b=b1−axi∈Acmax∣gi∣, and D=max(glj(d),grj(d)) 根据以上定理我们有以下讨论:(1)GOSS算法的渐进逼近率为 O ( 1 n l j ( d ) + 1 n r j ( d ) + 1 n ) \mathcal{O}\left(\frac{1}{n_{l}^{j}(d)}+\frac{1}{n_{r}^{j}(d)}+\frac{1}{\sqrt{n}}\right) O(nlj(d)1+nrj(d)1+n1)。如果划分过于不平衡(例如 n l j ( d ) ≥ O ( n ) n_{l}^{j}(d) \geq \mathcal{O}(\sqrt{n}) nlj(d)≥O(n), n r j ( d ) ≥ O ( n ) n_{r}^{j}(d) \geq \mathcal{O}(\sqrt{n}) nrj(d)≥O(n)),逼近误差将由公式(2)中的第二项主要决定,随着 n n n的增大会趋向于0。这意味着当数据量大时,逼近是相当准确的。(2)随机采样是GOSS算法的一种特殊情况,也就是当 a = 0 a=0 a=0时。在大多情况下GOSS算法的都比随机采样表现出色,限定条件为 C 0 , β > C a , β − a C_{0, \beta}>C_{a, \beta-a} C0,β>Ca,β−a,等效于 α a β > 1 − a β − a , α a = max x i ∈ A ∪ A c ∣ g i ∣ / max x i ∈ A c ∣ g i ∣ \frac{\alpha_{a}}{\sqrt{\beta}}>\frac{1-a}{\sqrt{\beta-a}},\alpha_{a}=\max _{x_{i} \in A \cup A^{c}}\left|g_{i}\right| / \max _{x_{i} \in A^{c}}\left|g_{i}\right| βαa>β−a1−a,αa=maxxi∈A∪Ac∣gi∣/maxxi∈Ac∣gi∣。
接下来我们分析GOSS算法的泛化性能。我们认为GOSS的泛化误差为 E g e n G O S S ( d ) = ∣ V ~ j ( d ) − V ∗ ( d ) ∣ \mathcal{E}_{g e n}^{G O S S}(d)=\left|\tilde{V}_{j}(d)-V_{*}(d)\right| EgenGOSS(d)=∣∣∣V~j(d)−V∗(d)∣∣∣,也就是采样后训练集的方差增益与原始分布真实方差增益之间的差值。我们可以推导得到 E g e n G O S S ( d ) ≤ ∣ V ~ j ( d ) − V j ( d ) ∣ + ∣ V j ( d ) − V ∗ ( d ) ∣ ≜ E G O S S ( d ) + E g e n ( d ) \mathcal{E}_{g e n}^{G O S S}(d) \leq\left|\tilde{V}_{j}(d)-V_{j}(d)\right|+\left|V_{j}(d)-V_{*}(d)\right| \triangleq \mathcal{E}_{G O S S}(d)+\mathcal{E}_{g e n}(d) EgenGOSS(d)≤∣∣∣V~j(d)−Vj(d)∣∣∣+∣Vj(d)−V∗(d)∣≜EGOSS(d)+Egen(d)。因此,如果GOSS算法的近似是准确的,GOSS的泛化误差接近基于全数据计算得到的泛化误差。从另一方面来说,采样将会提高基学习器的差异性,这样可以潜在地提高泛化能力。
4 Exclusive Feature Bundling
在本节中,我们提出了一种新的方法来有效地减少特征的数量。
高维数据通常是稀疏的。特征的稀疏性给我们设计一种近乎无损的降低特征维数的方法提供了可能性。具体来说,在稀疏特征空间中,许多特征是互斥的,即它们从不同时取非零值。我们可以放心的把互斥的特征捆绑成一个特征(这种方法我们叫做互斥特征捆绑)。通过精心设计的特征扫描算法,我们可以从捆绑特征构建出相同的直方图。用这种方法,当$ #bundle << #feature , 直 方 图 构 建 的 复 杂 度 就 从 ,直方图构建的复杂度就从 ,直方图构建的复杂度就从O(#data × #f eature) 变 成 了 变成了 变成了O(#data × #bundle)$(这里作者的意思是当远小于的时候效果才能凸显出来)。这样我们可以在不损伤精度的情况下大大加速GBDT的训练速度,下面我们将详细说明如何实现这一点。
这里有两个问题需要解决。第一个问题是如何决定哪些特征需要捆绑在一起。第二个问题是如何构建捆绑后的特征。
Theorem 4.1 达到最优的特征捆绑是NP难的。
Proof: 我们将图着色问题简化为我们的问题。因为图着色问题是NP难的,这样可以推断出我们的结论。
给定图着色问题中的任意样本点 G = ( V , E ) G=(V, E) G=(V,E)。下面我们构建我们的问题中的一个实例。以 G G G的关联矩阵中的每一行作为特征,通过此得到我们的问题中的一个具有 ∣ V ∣ |V| ∣V∣特征的实例。很容易看出,在我们的问题中一组互斥特征对应一组具有相同颜色的顶点,反之亦然。
(这块我是在不知道啥是图着色问题,所以翻译的有点…以后把图着色看会了再回来补充)
对于上面提到的第一个问题,我们证明了Theorem 4.1,也就是找到最优的捆绑策略是NP难的,这意味着在多项式时间内不可能找到一个精确解。为了寻找一个近似算法,我们把我们的问题简化成了一个图着色问题。将一个特征作为顶点,如果两个特征不是互斥特征就在二者之间增加一条边。然后我们使用贪心算法,贪心算法对于图着色问题可以得到一个相当好的结果(常数近似比率),进而可以转化成捆绑结果。除此之外,我们发现很多特征并不是100%互斥的,仍会有极少的时候同时取得非0值。如果我们的算法允许轻微的冲突,那么我们会得到更少的捆绑特征,可以进一步提高计算效率。通过简单的计算,随机改变一小部分特征值对精度的影响至多为 O ( [ ( 1 − γ ) n ] − 2 / 3 ) \mathcal{O}\left([(1-\gamma) n]^{-2 / 3}\right) O([(1−γ)n]−2/3)(看补充材料中的Proposition 2.1),其中 γ \gamma γ表示最大冲突率。所以我们如果选择一个相对小的 γ \gamma γ,我们就可以平衡精度和效率。
基于以上讨论,我们设计出一种针对互斥特征捆绑问题的算法,如Alg.3所示。首先,我们构建一个图,其边是带权的,权重由量特征之间的冲突率关联。其次,我们基于特征在图中的度数进行降序排序。最后,我们检查有序列表中的每个特征,要么将其分配给一个与其冲突率小(由γ控制)的现有捆绑特征,要么建立新的捆绑。算法Alg.3的时间复杂度为 O ( # f e a t u r e ) O(\# feature) O(#feature)且在训练之前仅处理一次。当特征数量没有那么大时这个复杂度是可以接受的,但如果面对几百万个特征就会受到很大的影响。为了大大提高效率,我们提出了一种不需要建图的更有效率的排序策略:依据非0值的数量进行排序。这与依据度数排序是相似的,因为非0值的数量多有几率制造更大的冲突。因为我们只改变了排序策略,所以省略新算法的细节以避免重复。
对于第二个问题,为了减少训练复杂度,我们需要一个好方法来合并应该捆绑的两个特征。关键是必须保证能从捆绑特征值中识别出原始特征的取值。因为基于直方图的算法存储离散的箱子而不是连续的特征值,我们可以通过使互斥特征分别从属不同的箱子来构造捆绑特征。这可以通过给原始特征添加偏移量来完成。举个例子,假设在一个捆绑特征里有两个特征需要合并。开始A特征的取值范围是 [ 0 , 10 ) [0,10) [0,10),B特征的取值范围是 [ 0 , 20 ) [0,20) [0,20)。然后我们给特征B添加一个10的偏移量,那么特征B的取值就变成了 [ 10 , 30 ) [10,30) [10,30)。之后我们就可以放心的合并特征A和B去代替原始的A和B,合并后的取值为 [ 0 , 30 ] [0,30] [0,30]。算法细节在Alg.4中体现。
EFB算法可以将很多互斥特征捆绑成少量的稠密特征,这样可以避免很多针对特征取值为0的不必要的计算。的确,我们可以优化基于直方图的算法,使用一张表来记录每个特征的非0取值。通过扫描这张表来建立直方图,每个特征建立直方图的复杂度就从 O ( # d a t a ) O(\# data) O(#data)变成了 O ( # n o n z e r o d a t a ) O(\# non_zero_data) O(#nonzerodata)。然而,在整棵树的建立过程中都需要花费额外的内存和算力去保存和更新这张表。我们在LightGBM中实现了这种优化并将其作为一个基本功能。值得注意的是,这种优化方法与EFB算法并不是冲突的,因为当捆绑后的特征依然稀疏时我们仍可以使用它。
5 Experiments
在本节中,我们报告关于我们提出的LightGBM算法的实验结果。我们利用五个公开的数据集做了实验。数据集的细节在Table1中列出。这些数据集中,微软的Learning to Rank(LETOR)数据集包含了30k的网络调查问卷。这些数据集中的特征大都是稠密的数值型特征。Allstate Insurance Claim和 Flight Delay都含有大量的独热编码的特征。最后两个数据集来自KDD CUP 2010和KDD CUP 2012。我们直接使用NTU的获胜的解决方案中的特征,其中同时包含稠密和稀疏特征且这两个数据集是非常大的。这些数据集都非常大,同时包含稠密和稀疏特征,并且涵盖很多实际中的任务需求。因此,我们可以利用他们彻底测试我们的算法。
5.1 Overall Comparison
我们在这个小节中进行了整体比较。利用XGBoost和不带GOOS和EFB算法的LightGBM(表示为lgb_baseline)作为基线。对于XGBoost我们用两种版本,一种是xgb_exa(基于预排序算法)和xgb_his(基于直方图算法)。对于xgb_his,lgb_baseline,和LightGBM,我们用leaf-wise的生长策略。对于xgb_exa,因为它仅支持layer-wise的生长策略,我们调整参数使其生长出和其他方法相似的树模型。我们同时也针对所有数据集调整参数以平衡效率和精度。我们设置针对Allstate,KDD10和 KDD12设置 a = 0.05 , b = 0.05 a = 0.05,b = 0.05 a=0.05,b=0.05, 针对Flight Delay和LETOR设置 a = 0.1 , b = 0.1 a = 0.1, b = 0.1 a=0.1,b=0.1。在EFB算法中设置 γ = 0 \gamma=0 γ=0。所有算法都运行的迭代次数都是固定的,我们取最优迭代结果作为最终结果。
Table1:实验中用的数据集
Table2:综合训练时间对比。LightGBM是lgb_baseline配合GOSS算法和EFB算法。EFB_only是lgb_baseline仅配合EFB算法。表中的数值是训练迭代一次的平均用时。
Table3:测试集上的综合精度对比。用AUC评价分类任务,用NDCG@10评价排序任务。SGB是lgb_baseline配合随机梯度下降算法,它的采样率与Li ghtGBM相同。
Table4:在数据集LETOR上基于不同采样率GOSS和SGB准确率的比较。我们通过设置很大的最大迭代次数和早停来保证收敛。不同设置的标准偏差很小。GOS的 a a a和 b b b的设置可以在补充材料中找到。
训练时间和测试精度在表2和表3中分别总结了。从这些结果中我们可以看出,LightGBM在维持与基线几乎相同的精度的同时是最快的。xgb_exa基于预排序算法,相比基于直方图算法的慢了很多。通过与基线lgb_baseline对比,LightGBM在数据集Allstate, Flight Delay, LETOR, KDD10和KDD12中分别加速了21x,6x,1.6x,14x和13x。由于xgb_his内存消耗非常大,因为内存不足无法成功在数据集KDD10和KDD12上跑通。在其余的数据集上,LightGBM都更快,在数据集Allstate上达到了9X的加速。加速的计算是基于每次训练迭代消耗的时间,因为所有算法经过差不多相同的迭代次数后都会收敛。为了展示整个训练过程,我们在图1和图2中分别展示了数据集Flight Delay和LETOR上基于时间的训练曲线。为了节省空间,我们把其他数据集的训练曲线放在补充材料中展示。
在所有的数据集上,LightGBM可以达到与基线几乎相同的精度。这说明GOSS和EFB在显著加速的同时不会影响精度。这与我们在3.2和4中的理论分析是一致的。
5.2 Analysis on GOSS
首先,我们研究GOSS的加速能力。从表2的LightGBM和EFB_only(LightGBM without GOSS),我们可以看出GOSS通过利用10%-20%的数据可以带来2X的加速。GOSS算法仅仅利用采样后的数据来学习决策树。然而,它仍保留了一些在完整数据集上的计算,例如预测和梯度的计算。因此,我们可以发现整体加速与数据的采样率并不是线性相关的。当然,GOSS算法带来的加速仍然意义重大,而且它普遍适用与不同的数据集。
然后,我们通过与随机梯度下降(SGB)做对比评估了GOSS的精度。为了不失一般性,我们用LETOR来作为测试集。我们通过设置GOSS中的 a a a和 b b b来设置采样率,并将同样的采样率应用于SGB中。基于这些参数设置和早停将模型迭代至收敛。结果如表4所示。我们可以看到在相同的采样率下,GOSS的精度仍然优于SGB。这些结果与我们在3.2中的讨论是一致的。所有的实验结果都证明了GOSS是一种比随机采样更有效率的采样方法。
5.3 Analysis on EFB
我们通过对比lgb_baseline和EFB_only来检验EFB算法对加速的贡献度。结果如表2所示。这里我们不允许捆绑特征之间有冲突率(即, γ = 0 \gamma=0 γ=0)。我们可以发现EFB算法在大规模数据上可以显著提速。
请注意lgb_baseline已经对稠密特征进行了优化,EFB算法仍然可以(在此基础上)极大的提高训练速度。这是因为EFB将许多稀疏特征(包括独热编码特征和隐式互斥特征)合并成相对少很多的特征。捆绑的过程中包含了基本的稀疏特征优化。然而,EFB不需要在树模型的学习过程中为每个特征记录非零数据表花费额外成本。更重要的是,由于许多先前独立的特征捆绑在一起,可以显著改善空间局限性并提高缓存命中率。因此,整体效率的提高是引人注目的。通过以上分析,EFB是一种非常有效的基于直方图算法的稀疏特征处理算法,可以为GBDT训练过程显著加速。
6 Conclusion
本文我们提出了一种新的GBDT算法,叫LightGBM,它包含两种新的技术:基于梯度的单侧采样和互斥特征捆绑,分别用来应对数据量大和特征维度高的情况。我们对这两种技术进行了理论分析和实验研究。实验结果与理论相一致,在GOSS和EFB算法的帮助下,LightGBM在计算速度和内存消耗方面明显优于XGBoost和SGB。在未来的工作中,我们将研究基于梯度的单侧采样算法中的 a a a和 b b b的参数选择,并继续改进互斥特征捆绑算法的性能以高维特征,无论稀疏与否。