LightGBM优势总结
lightgbm对于类别变量的处理
效率和内存上的提升
1) 在训练决策树计算切分点的增益时,xgboost采用预排序,即需要对每个样本的切分位置都要计算一遍,所以时间复杂度是O(#data)。
而LightGBM则是将样本离散化为直方图,直方图算法的基本思想是先把连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图。在遍历数据的时候,根据离散化后的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点)
Histogram 算法的优缺点:
- Histogram算法并不是完美的。由于特征被离散化后,找到的并不是很精确的分割点,所以会对结果产生影响。但在实际的数据集上表明,离散化的分裂点对最终的精度影响并不大,甚至会好一些。原因在于decision tree本身就是一个弱学习器,采用Histogram算法会起到正则化的效果,有效地防止模型的过拟合。
- 时间上的开销由原来的O(#data * #features)降到O(k * #features)。由于离散化,#bin远小于#data,因此时间上有很大的提升。
- Histogram算法还可以进一步加速。一个叶子节点的Histogram可以直接由父节点的Histogram和兄弟节点的Histogram做差得到。一般情况下,构造Histogram需要遍历该叶子上的所有数据,通过该方法,只需要遍历Histogram的k个捅。速度提升了一倍。
这样再计算分裂点增益时只需要根据直方图切割位置计算即可,时间复杂度缩减为O(#bins),比如原始数据是100条,需要进行100次切割计算,如果分成10个直方图之后,只需要进行10次分割计算即可,时间效率上大大提高了。直方图算法是一种牺牲了一定的切分准确性而换取训练速度以及节省内存空间消耗的算法。(初始构造直方图是需要一次O(#data)的时间复杂度,不过这里只涉及到加和操作)
2)直方图做差进一步提高效率,计算某一节点的叶节点的直方图可以通过将该节点的直方图与另一子节点的直方图做差得到,所以每次分裂只需计算分裂后样本数较少的子节点的直方图然后通过做差的方式获得另一个子节点的直方图,进一步提高效率
3)节省内存
- 将连续数据离散化为直方图的形式,对于数据量较小的情形可以使用小型的数据类型来保存训练数据
- 不必像预排序一样保留额外的对特征值进行预排序的信息
稀疏特征优化
对稀疏特征构建直方图时的时间复杂度为O(2*#非零数据)
带深度限制的Leaf-wise的叶子生长策略
Level-wise过一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上Level-wise是一种低效的算法,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销,因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。
Leaf-wise则是一种更为高效的策略,每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。Leaf-wise的缺点是可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。
直接支持类别特征
lightGBM可以直接用类别特征进行训练,不必预先进行独热编码,速度会提升不少,参数设置categorical_feature
来指定数据中的类别特征列。
对于类别类型特征我们原始的做法是进行独热编码,但是这种做法对于基于树的模型而言不是很好,对于基数较大的类别特征,可能会生成非常不平衡的树并且需要一颗很深的树才能达到较好的准确率;比较好的做法是将类别特征划分为两个子集,直接划分方法众多(2^(k-1)-1),对于回归树而言有一种较高效的方法只需要O(klogk)的时间复杂度,基本思想是对类别按照与目标标签的相关性进行重排序,具体一点是对于保存了类别特征的直方图根据其累计值(sum_gradient/sum_hessian)重排序,在排序好的直方图上选取最佳切分位置。
特征并行减少通信传输代价
特征并行是为了将寻找决策树的最佳切分点这一过程并行化
- 传统做法
- 对数据列采样,即不同的机器上保留不同的特征子集
- 各个机器上的worker根据所分配的特征子集寻找到局部的最优切分点(特征、阈值)
- 互相通信来从局部最佳切分点里得到最佳切分点
- 拥有最佳切分点的worker执行切分操作,然后将切分结果传送给其他的worker
- 其他的worker根据接收到的数据来切分数据
- 传统做法的缺点
- 计算量太大,并没有提升切分的效率,时间复杂度为O(#data)(因为每个worker持有所有行,需要处理全部的记录),当数据量较大时特征并行并不能提升速度
- 切分结果的通信代价,大约为O(#data/8)(若一个数据样本为1bit)
- LightGBM的做法
让每个机器保留整个完整的数据集(并不是经过列采样的数据),这样就不必在切分后传输切分结果数据,因为每个机器已经持有完整的数据集- 各个机器上的worker根据所分配的特征子集寻找到局部的最优切分点(特征、阈值)
- 互相通信来从局部最佳切分点里得到最佳切分点
- 执行最优切分操作
Notes:典型的空间换时间,差别就是减少了传输切分结果的步骤,节省了这里的通信消耗
数据并行
上述特征并行的方法并没有根本解决寻找切分点的计算效率问题,当记录数过大时需要考虑数据并行的方法
- 传统做法
- 行采样,对数据进行横向切分
- worker使用分配到的局部数据构建局部的直方图
- 合并局部直方图得到全局的直方图
- 对全局直方图寻找最优切分点,然后进行切分
- 缺点:通信代价过高,若使用point-to-point的通信算法,每个机器的通信代价时间复杂度为O(#machine*#feature*#bin),若使用collective通信算法则通信代价为O(2*#feature*#bin)
- LightGBM的做法(依然是降低通信代价)
- 不同于合并所有的局部直方图获得全局的直方图,LightGBM通过Reduce Scatter方法来合并不同worker的无交叉的不同特征的直方图,这样找到该直方图的局部最优切分点,最后同步到全局最优切分点
- 基于直方图做差的方法,在通信的过程中可以只传输某一叶节点的直方图,而对于其邻居可通过做差的方式得到
- 通信的时间复杂度为O(0.5*#feature*#bin)