文章目录

lightGBM 简介
GBDT是个经典的模型,主要是利用弱分类器(决策树)迭代训练以得到最优模型,该模型具有训练效果好、不易过拟合等优点,常被用于多分类、点击率预测、搜索排序等任务。
在LightGBM提出之前,还有个GBDT的高效实现:XGBoost。XGBoost是属于boosting家族,也是GBDT算法的一个工程实现。 在模型的训练过程中是聚焦残差,在目标函数中使用了二阶泰勒展开并加入了正则,在决策树的生成过程中采用近似分割的方式(可以理解为分桶的思路),选出一些候选的分裂点,然后再遍历这些较少的分裂点,计算按照这些候选分裂点位分裂后的全部样本的目标函数增益,找到最大的那个增益对应的特征和候选分裂点位,从而进行分裂。这样一层一层的完成建树过程, XGBoost训练的时候,是通过加法的方式进行训练,也就是每一次通过聚焦残差训练一棵树出来, 最后的预测结果是所有树的加和表示。
对于上面的过程,不难发现时间复杂度和空间复杂度比较高:
- 首先就是空间消耗很大,因为预排序的话既需要保存数据的特征值, 还得保存特征排序后的索引,毕竟这样后续计算分割点的时候快一些,但是这样就需要消耗训练数据两倍的内存。
- 其次, 时间上也有很大的开销,在遍历每一个分割点的时候,都需要进行分裂增益的计算,消耗的代价大。
总的来说,XGBoost寻找最优分裂点的复杂度由下面三个因素构成:
特 征 数 量 × 分 裂 点 的 数 量 × 样 本 的 数 量 特征数量×分裂点的数量×样本的数量 特征数量×分裂点的数量×样本的数量
LightGBM(Light Gradient Boosting Machine)也是一个实现GBDT算法的框架,支持高效率的并行训练,并且具有更快的训练速度、更低的内存消耗、更好的准确率、支持分布式可以快速处理海量数据等优点。它主要对上面的三个因素分别优化,下面提到的1,直方图算法就是为了减少分裂点的数量, 2,单边梯度抽样算法就是为了减少样本的数量,3, 互斥特征捆绑算法就是为了减少特征的数量。 并且后面两个是Lightgbm的亮点所在。
直方图算法(Histogram algorithm)
基本思想
直方图算法的基本思想是:先把连续的浮点特征值离散化成 k 个整数,同时构造一个宽度为 k 的直方图。在遍历数据的时候,根据离散化后的值作为索引在直方图中累积计数,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。如下图所示:
XGBoost 在进行预排序时只考虑非零值进行加速,而 LightGBM 也采用类似策略:只用非零特征构建直方图。这种离散化分桶思路其实有很多优点的, 首先最明显就是内存消耗的降低,XGBoost 需要用32位的浮点数去存储特征值, 并用32位的整型去存储索引:
而Lightgbm的直方图算法不仅不需要额外存储预排序的结果,而且可以只保存特征离散化后的值,而这个值一般用8位整型存储就足够了,即内存消耗从32+32变为了8,降低为原来的1/8。
同时,计数复杂度也大幅度降低,XGBoost的预排序算法每遍历一个特征值就需要计算一次分裂的增益,而Lightgbm直方图算法只需要计算k次(k可以认为是常数):
时间复杂度从:
O ( ( 特 征 取 值 个 数 − 1 ) × 特 征 个 数 ) O((特征取值个数−1)× 特征个数) \\ O((特征取值个数−1)×特征个数)
变为:
O ( ( 分 桶 数 − 1 ) × 特 征 个 数 ) O((分桶数−1)× 特征个数) O((分桶数−1)×特征个数)
其中,特征取值个远大于分桶树。
直方图做差
实际上,直方图算法还可以进一步加速。一般情况下,构造直方图需要遍历该叶子上的所有数据才行。但是对于二叉树而言,一个叶子节点的直方图可以直接由父节点的直方图和兄弟节点的直方图做差得到:
通过该方法,只需要遍历直方图的k个捅,速度提升了一倍。
举个例子,假设有15个训练样本,2个特征 x 1 , x 2 x_1,x_2 x