引言https://blog.csdn.net/ShowMeAI/article/details/123406621 之前ShowMeAI对强大的boosting模型工具XGBoost做了介绍(详见ShowMeAI文章图解机器学习 | XGBoost模型详解)。本篇我们来学习一下GBDT模型(详见ShowMeAI文章 图解机器学习 | GBDT模型详解)的另一个进化版本:LightGBM。 LightGBM是微软开发的boosting集成模型,和XGBoost一样是对GBDT的优化和高效实现,原理有一些相似之处,但它很多方面比XGBoost有着更为优秀的表现。官方给出的这个工具库模型的优势如下:
下图是一组实验数据,在这份实验中,LightGBM比XGBoost快将近10倍,内存占用率大约为XGBoost的1/6,准确率也略有提升。 1.LightGBM动机互联网领域的算法应用,通常背后都有海量的大数据。深度学习中一系列神经网络算法,都是以mini-batch的方式喂数据迭代训练的,总训练数据量不受内存限制。 但我们用到的机器学习算法,比如GBDT(参考ShowMeAI文章 GBDT详解)在每一次迭代的时候,都需要遍历整个训练数据多次。
面对工业级海量的数据,普通的GBDT算法无法满足需求。LightGBM提出的主要原因之一,就是为了解决上述大数据量级下的GBDT训练问题,以便工业实践中能支撑大数据量并保证效率。 2.XGBoost优缺点我们之前介绍过强大的XGBoost(详见ShowMeAI文章图解机器学习 | XGBoost模型详解),但XGBoost也依旧存在一些缺点,LightGBM针对其中的一部分进行了调整优化。XGB优缺点归纳如下: 1)精确贪心算法轮迭代时,都需要遍历整个训练数据多次。如果把整个训练数据装进内存则会限制训练数据的大小;如果不装进内存,反复地读写训练数据又会消耗非常大的时间。 G a i n = 1 2 [ G L 2 H L + λ + G R 2 H R + λ − ( G L + G R ) 2 H L + H R + λ − γ ] Gain=\frac{1}{2}\left [ \frac{G_{L}^{2}}{H_{L}+\lambda} + \frac{G_{R}^{2}}{H_{R}+\lambda} - \frac{\left(G_{L}+G_{R}\right)^{2}}{H_{L}+H_{R}+\lambda} - \gamma \right ] Gain=21[HL+λGL2+HR+λGR2−HL+HR+λ(GL+GR)2−γ]
2)Level-wise生长方式XGBoost采用Level-wise的增长策略:基于层进行生长,直到达到停止条件。这种增长策略方便并行计算每一层的分裂节点,提高了训练速度,但同时也因为节点增益过小增加了很多不必要的分裂,增加了计算量。
3)对cache优化不友好在预排序后,特征对梯度的访问是一种随机访问,并且不同的特征访问的顺序不一样,无法对cache进行优化。同时,在每一层长树的时候,需要随机访问一个行索引到叶子索引的数组,并且不同特征访问的顺序也不一样,也会造成较大的cache miss。 3.LightGBM优化点上个部分其实也是LightGBM作者们,构建新算法时着重优化的点。概括来说,LightGBM主要有以下特点:
4.决策树算法1)XGBoost:Pre-sorted算法XGBoost使用的是Pre-sorted算法,能够更精确的找到数据分隔点。
这种pre-sorting算法能够准确找到分裂点,但是在空间和时间上有很大的开销。
2)LightGBM:直方图算法LightGBM使用的是直方图算法(histogram algorithm),占用的内存更低,数据分割的复杂度更低。直方图算法思想是:
(1)内存优化直方图算法可以很大程度降低内存消耗,它不仅不需要额外存储预排序的结果,还可以只保存特征离散化后的值(一般用8位整型存储就足够了)。 如图所示,用8位整型存储,内存消耗可以降低为原来的1/8。 (2)计算量优化应用直方图算法,计算代价也大幅降低,预排序算法每遍历一个特征值就需要计算一次分裂的增益,而直方图算法只需要计算k次(k可以认为是常数),时间复杂度从O(#data*#feature)直接优化到 O(k#*features)。 (3)注意点直方图算法的理解和注意点如下:
(4)直方图算法优缺点
Histogram算法还可以进一步加速。一个叶子节点的Histogram可以直接由父节点的Histogram和兄弟节点的Histogram做差得到。一般情况下,构造Histogram需要遍历该叶子上的所有数据,通过该方法,只需要遍历Histogram的k个捅。速度提升了一倍。 5.决策树生长策略1)树生长策略调整直方图算法之上,LightGBM进行进一步的优化。它没有使用大多数GBDT工具使用的按层生长(Level-wise)的决策树生长策略,而使用了带有深度限制的按叶子生长(Leaf-wise)算法。 ( p m , f m , v m ) = arg min ( p , f , v ) L ( T m − 1 ( X ) . split ( p , f , v ) , Y ) \left(p_{m}, f_{m}, v_{m}\right)=\arg \min _{(p, f, v)} L\left(T_{m-1}(X) . \operatorname{split}(p, f, v), Y\right) (pm,fm,vm)=arg(p,f,v)minL(Tm−1(X).split(p,f,v),Y) T m ( X ) = T m − 1 ( X ) . split ( p m , f m , v m ) T_{m}(X)=T_{m-1}(X) . \operatorname{split}\left(p_{m}, f_{m}, v_{m}\right) Tm(X)=Tm−1(X).split(pm,fm,vm) 2)XGBoost:Level-wiseXGBoost采用的是Level-wise(按层生长)策略生长的,能够同时分裂同一层的叶子,从而进行多线程优化,不容易过拟合。 但不加区分的对待同一层的叶子,带来了很多没必要的开销。因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。 3)LightGBM:Leaf-wiseLightGBM采用Leaf-wise(按叶子生长)生长策略,每次从当前所有叶子中找到分裂增益最大(一般也是数据量最大)的一个叶子,然后分裂,如此循环。 同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。Leaf-wise的缺点是可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。 6.直方图差加速LightGBM另一个优化是Histogram(直方图)做差加速。整个构建过程中可以观察到:一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到。 一般来说构造直方图,需要遍历该叶子上的所有数据,但直方图做差仅需遍历直方图的k个桶。利用上述特征,LightGBM可以在构造一个叶子的直方图后,可以用非常微小的代价得到它兄弟叶子的直方图,在速度上可以提升一倍。 7.类别型特征支持大多数机器学习工具都无法直接支持类别型特征,我们会先将其编码再做后续建模,如果使用one-hot这种编码方式还会降低空间和时间效率。 LightGBM优化了对类别型特征的支持,可以直接输入类别特征,不需要额外的编码或one-hot 0/1展开。并在决策树算法上增加了类别型特征的决策规则。 1)树模型与one-hot编码one-hot编码是处理类别特征的一个通用方法,然而在树模型中,这可能并不一定是一个好的方法,尤其当类别特征中类别个数很多的情况下,主要的问题是: 问题1:可能无法在这个类别特征上进行切分。 使用one-hot编码的话,意味着在每一个决策节点上只能使用one vs rest(例如是不是男性,是不是一线城市等)的切分方式。当类别值很多时,每个类别上的数据可能会比较少,这时候切分会产生不平衡,这意味着切分增益也会很小。 问题2:影响决策树的学习。 就算可以在这个类别特征进行切分,也会把数据切分到很多零碎的小空间上,如下左图所示。而决策树学习时利用的是统计信息,在这些数据量小的空间上,统计信息不准确,学习会变差。但如果使用下右图的分裂方式,数据会被切分到两个比较大的空间,进一步的学习也会更好。 圈中的数值表示该结点内的数据。右图中叶子节点 X=A || X=C 的含义是 X=A 或者 X=C 放到左孩子,其余放到右孩子。 2)LightGBM类别型特征处理方式LightGBM采用了Many vs Many的切分方式解决one-hot编码带来的问题,实现了类别特征的最优切分。用LightGBM可以直接输入类别特征,并产生上右图的效果。 算法流程如图所示:
从下图可以看到,Sum(y)/Count(y)为类别的均值。当然,这个方法很容易过拟合,所以在LightGBM中加入了很多对这个方法的约束和正则化。 求解类别型特征的最优切分的具体流程如下: ① 离散特征建立直方图的过程 统计该特征下每一种离散值出现的次数,并从高到低排序,并过滤掉出现次数较少的特征值。然后为每一个特征值,建立一个bin容器,对于在bin容器内出现次数较少的特征值直接过滤掉,不建立bin容器。 ② 计算分裂阈值的过程
该 b i n 容 器 下 所 有 样 本 的 一 阶 梯 度 之 和 该 b i n 容 器 下 所 有 样 本 的 二 阶 梯 度 之 和 + 正 则 项 ( 参 数 c a t - s m o o t h ) \frac{该bin容器下所有样本的一阶梯度之和}{该bin容器下所有样本的二阶梯度之和} + 正则项(参数 {cat \text{-} smooth}) 该bin容器下所有样本的二阶梯度之和该bin容器下所有样本的一阶梯度之和+正则项(参数cat-smooth) 这里为什么不是label的均值呢?其实上例中只是为了便于理解,只针对了学习一棵树且是回归问题的情况。这时候一阶导数是Y,二阶导数是1),
③ 对于连续特征,划分阈值只有一个。对于离散值可能会有多个划分阈值,每一个划分阈值对应着一个bin容器编号。 当使用离散特征进行分裂时,只要数据样本对应的bin容器编号在这些阈值对应的bin集合之中,这条数据就加入分裂后的左子树,否则加入分裂后的右子树。 8.并行支持与优化LightGBM原生支持并行学习,目前支持「特征并行」和「数据并行」的两种,LightGBM针对这两种并行方法都做了优化。
1)特征并行LightGBM在特征并行算法中,通过在本地保存全部数据避免对数据切分结果的通信。 2)数据并行Lightgbm在数据并行中使用分散规约(Reduce scatter)把直方图合并的任务分摊到不同的机器,降低通信和计算,并利用直方图做差,进一步减少了一半的通信量。 基于投票的数据并行则进一步优化数据并行中的通信代价,使通信代价变成常数级别。在数据量很大的时候,使用投票并行可以得到非常好的加速效果。
9.网络通信优化XGBoost由于采用Pre-sorted算法,直接通信代价比较大;LightGBM采用的histogram算法通信代价小,通过使用集合通信算法,能够实现并行计算的线性加速。 10.参考资料 |
|