flydreamforever 2018-08-18
先show 一下:
30万样本,40维特征,lightGBM在22秒内跑完,速度惊人,比xgboost快不少,精度与xgboost不相上下。但是易用性和特性相比xgboost还有待提高,cv,early stopping这两个我觉得非常重要的特性并没有找到
大多数机器学习工具都无法直接支持类别特征作为输入,一般需要转换成多维0/1特征,带来计算和内存上的额外消耗。LightGBM增加了针对于类别特征的决策规则,这在决策树上也很好实现。主要的思想是,在对类别特征计算分割增益的时候,不是按照数值特征那样由一个阈值进行切分,而是直接把其中一个类别当成一类,其他的类别当成另一类。这实际上与0/1展开的效果是一样的。
GBDT 虽然是个强力的模型,但却有着一个致命的缺陷,不能用类似 mini batch 的方式来训练,需要对数据进行无数次的遍历。如果想要速度,就需要把数据都预加载在内存中,但这样数据就会受限于内存的大小;如果想要训练更多的数据,就要使用外存版本的决策树算法。虽然外存算法也有较多优化,SSD 也在普及,但在频繁的 IO 下,速度还是比较慢的。
为了能让 GBDT 高效地用上更多的数据,我们把思路转向了分布式 GBDT, 然后就有了 LightGBM。设计的思路主要是两点,1. 单个机器在不牺牲速度的情况下,尽可能多地用上更多的数据;2.
多机并行的时候,通信的代价尽可能地低,并且在计算上可以做到线性加速。
基于这两个需求,LightGBM 选择了基于 histogram 的决策树算法。相比于另一个主流的算法 pre-sorted(如 xgboost 中的 exact 算法),histogram 在内存消耗和计算代价上都有不少优势。
当然, histogram 算法也有缺点,它不能找到很精确的分割点,训练误差没有 pre-sorted 好。但从实验结果来看, histogram 算法在测试集的误差和 pre-sorted 算法差异并不是很大,甚至有时候效果更好。实际上可能决策树对于分割点的精确程度并不太敏感,而且较“粗”的分割点也自带正则化的效果。
在 histogram 算法之上, LightGBM 进行进一步的优化。首先它抛弃了大多数 GBDT 工具使用的按层生长
(level-wise) 的决策树生长策略,而使用了带有深度限制的按叶子生长 (leaf-wise) 算法。 level-wise 过一次数据可以同时分裂同一层的叶子,容易进行多线程优化,不容易过拟合。但实际上level-wise是一种低效的算法,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销。因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。leaf-wise则是一种更为高效的策略,每次从当前所有叶子中,找到分裂增益最大(一般也是数据量最大)的一个叶子,然后分裂,如此循环。因此同 level-wise 相比,在分裂次数相同的情况下,leaf-wise 可以降低更多的误差,得到更好的精度。leaf-wise 的缺点是可能会长出比较深的决策树,产生过拟合。因此 LightGBM 在leaf-wise 之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。
另一个比较巧妙的优化是 histogram 做差加速。一个容易观察到的现象:一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到。通常构造直方图,需要遍历该叶子上的所有数据,但直方图做差仅需遍历直方图的 k 个桶。利用这个方法,LightGBM 可以在构造一个叶子的直方图后,可以用非常微小的代价得到它兄弟叶子的直方图,在速度上可以提升一倍。
https://github.com/Microsoft/LightGBM