1 速度和内存使用优化
许多 boost 工具使用基于预排序的算法(例如 xgboost 中的默认算法)进行决策树学习。这是一个简单的解决方案,但不容易优化。
LightGBM 使用基于直方图的算法,将连续的特征(属性)值分门别类。这加快了训练速度,减少了内存的使用。基于直方图的算法的优势包括以下几点:
-
减少了计算每个分支增益的消耗
基于预排序的算法具有时间复杂度 O(#data)计算直方图的时间复杂度为 O(#data),但这只涉及到快速求和操作。一旦构建了直方图,基于直方图的算法的时间复杂度为 O(#bins),而 #bins 远远小于 #data。
-
使用直方图减法来进一步提速
要得到二叉树中一片叶子的直方图,可以使用它的父叶和邻叶的直方图做减法。所以它只需要构造一个叶子的直方图(其 #data 比其邻居小),然后它可以用小成本 O(#bins) 通过直方图减法得到其邻居的直方图。
-
减少内存使用量
用离散 bins 代替连续值。如果 #bins 很小,可以使用小数据类型,如 uint8_t,来存储训练数据。
无需为预排序特征值存储额外信息
-
降低并行学习的通信成本
2 稀疏优化
只需要 O(2 * #非零数据) 来构建稀疏特征的直方图。
3 准确度优化
Leaf-wise (Best-fist) Tree Growth
大多数的决策树都是按照 level(depth)-wise 方式生长
LightGBM 将选择 delta loss 最大的叶子来生长。在叶子数量相同情况下,leaf-wise 算法往往比 level-wise 算法实现更低的损失。
当#data较小时,Leaf-wise 可能会导致过拟合,LightGBM 使用 max_depth 参数来限制树的深度。然而,即使指定了 max_depth,树仍然会生长叶子,所以仍然要小心过拟合。
4 类别特征划分优化
一般用 one-hot 编码来表示分类特征,但这种方法对于树学习器来说是次优的。特别是对于类别数目大的特征,建立在 one-hot 特征上的树往往是不平衡的,需要生长到很深才能达到很好的精度。
比较好的方法是在类别特征上进行拆分,将其类别划分为2个子集。如果该特征有 k 个类别,则有 2^(k-1) - 1
个可能的分区。但是对于回归树来说,有一个高效的解决方案1,它大约需要 O(k * log(k))
找到最优分区。
基本思路是在每次分割时根据训练目标对类别进行排序。更具体地说,LightGBM 根据直方图(对于一个类别特征)的累积值(sum_gradient / sum_hessian)进行排序,然后在排序后的直方图上找到最佳分割。
5 网络通信优化
在 LightGBM 的并行学习中使用一些集体通信算法,如 “All reduce”、"All gathering "和 “Reduce scatter”。LightGBM 实现了最先进的算法2。这些集体通信算法可以提供比点对点通信更好的性能。
6 并行优化
特征优化
特征并行的目的是将决策树中的 "寻找最佳分割 "并行化。
传统算法
传统特征并行的过程是:
- 对数据进行垂直分割(不同机器有不同的特征集)。
- Workers 在局部特征集上找到局部最佳分割点{特征,阈值}。
- 互相交流局部的最佳分割点,得到最佳分割点。
- 最佳分割点的 Worker 进行分割,然后将数据的分割结果发送给其他 Workers。
- 其他 Workers 根据接收到的数据进行数据分割。
缺点:
- 有计算开销,因为它不能加快 "分割 "的速度,而 "分割 "的时间复杂度是O(#data)。因此,当#data很大时,特征并行不能很好地提速。
- 需要对拆分结果进行通信,其成本约为
O(#data / 8)
(一个数据一个位)。
Lightgbm 的特征并行
数据量很大的时候,特征并行不能很好的加速,所以我们做了一个小小的改变:不对数据进行垂直分区,而是每个 worker 都持有全部数据。这样,LightGBM 就不需要为数据的分割结果进行通信,因为每个 worker 都知道如何分割数据。而且数据也不会变大,所以在每台机器上都持有完整的数据是合理的。
LightGBM中特征并行的过程:
- Workers 在本地特征集上找到本地最佳分割点 {feature, threshold}。
- 互相交流本地最佳分割点,并得到最佳分割点。
- 进行最佳分割。
但是,当数据量很大时,这种特征并行算法仍然存在 “分裂” 的计算开销。所以当数据量很大时,使用数据并行会更好。
数据并行
数据并行的目的是将整个决策学习并行化
传统算法
数据并行的流程是:
- 将数据进行横向分割。
- 使用局部数据构建局部直方图。
- 从所有局部直方图中合并全局直方图。
- 从合并后的全局直方图中找到最佳分割,然后进行分割。
缺点:
- 通信成本高。如果使用点对点通信算法,一台机器的通信成本约为
O(#machine * #feature * #bin)
。如果使用集体通信算法(如 “All reduce”),通信成本约为O(2 * #feature * #bin)
。
Lightgbm 的数据并行
我们降低了 LightGBM 中数据并行的通信成本:
- LightGBM 使用 “Reduce Scatter” 代替 “Merge global histograms from all local histograms”,来合并不同 Workers 的不同(非重叠)特征的直方图。然后 Workers 在本地合并直方图上找到本地最佳分割,并同步全局最佳分割。
- 如前所述,LightGBM 使用直方图减法来加快训练速度。在此基础上,我们可以只通信一片叶子的直方图,也通过减法得到其邻居的直方图。
ps: 什么是 Reduce、Scatter,这里 有一个简单说明
综合考虑,LightGBM中数据并行的时间复杂度为 O(0.5 * #feature * #bin)
。
7 并行投票
并行投票进一步将数据并行中的通信成本降低到恒定成本。它采用两级投票来降低特征直方图的通信成本3。