对LightGBM的一点理解

LightGBM是微软团队2017年发表在NIPS的一篇论文,也是一种基于GBDT的Boosting的方法。之前有了各种Boosting方法,以及在各类数据比赛中大放异彩的XGBoost,LightGBM的优势在哪里呢?

LightGBM是一种基于GBDT的提升方法。对于这类基于树的模型,最耗时的部分就是在进行特征选择结点分裂时,需要遍历所有可能的划分点,计算信息增益,从而找到最优的划分点。前面虽然有了各类的算法对这个过程进行优化,比如XGBoost,但是在特征维数很高,样本量很大的情况下,它的效率和灵活性还是不够好。因此,本文的作者提出了LightGBM这个模型,极大的提升了计算效率。根据论文里的说法,在模型精度和GBDT差不多的情况下训练速度比它快了20倍。所以,LightGBM这个模型的提出,所要解决的主要问题是计算效率的问题。在快的同时,还能保证模型的精度,这是它最大的优点。

为了让GBDT快起来,入手的方向只有两个,要不就减少特征数,这样在进行特征选择结点分裂的时候能够减少计算量,提高速度;要不就减少训练样本数,这样也能减少计算量,提高效率。但是这样做缺点很明显,牺牲了模型的精度啊!有没有什么两全其美的方法呢?

在介绍LightGBM的方法之前,我们先回顾一下之前的一些模型是怎么做的。
对于一些采用行采样进行加速的模型,根据的是样本的权重进行的采样(比如AdaBoost模型,在训练过程中会提升那些之前被误分类的样本的权重),但是对与GBDT来说这就不适用了,因为它的样本是没有权重的;不需要利用样本权重的模型,比如SGD(随机梯度提升),通过随机行采样的方式减少计算量,虽然可以应用到GBDT,但是显然会损失模型的精度。

对于列采样过程中的优化,比如随机森林,并不对所有的特征都做计算,而是随机选择几个特征,从这里面选择最优的属性,减小了计算量。

本文的优化方法,就是在行采样和列采样两个方面,提出了更胜一筹的优化方法,从而在不牺牲精度的条件下,极大的提升了训练速度!

  • 针对行采样的优化,提出了GOSS(Gradient-based One-side Sampling)
  • 针对列采样,提出了EFB(Exclusive Feature Bundling)

GOSS

LigntGBM也好,XGBoost也好,都是提升方法,基于GBDT,建树的过程是串行化的过程,所以在Tree层面上是不能够并行化处理的。可以进行加速提升的部分,就是在进行特征选择结点分裂的时候,而这也是建树中最耗时的部分。比较常用的优化方法,一种是对特征值先进行排序,然后计算每个划分点的增益,存起来,最后通过查表比较的方式进行选择,相当于用空间换时间;还有就是基于直方图的方法。XGBoost中提供了这两种方法的实现。
而本文呢,是注意到在训练过程中,如果一个样本产生的梯度很小,说明它的训练误差很小,基本上是well-trained的。这就为行采样提供了一个依据,选择那些梯度大的样本进行训练,对于梯度小的可以drop掉。但是这样会带来一个问题,改变了训练样本的分布。GOSS呢,就提出不把这些梯度小的舍弃掉,而是设置一个采样比例,留下一部分,但是为了弥补丢掉的那一部分的数据在计算增益时的作用,对这些留下的小梯度的样本乘个系数。
举个例子:整个训练样本大小为100,当计算完梯度之后,对每个样本的梯度绝对值按从大到小排序,假如设置a的比例,作为梯度大的数据,这部分的集合记作A,剩下的就是认为梯度小的比例,在这基础上,再乘b,随机选择这么多的小梯度的样本加入到训练集中。不过在计算增益的时候要对这些小梯度的样本乘个系数 1ab 1 − a b 作为放大,弥补采样的缺失。通过采用这种方法,既减少了训练样本,提高了模型对那些还没有训练好的样本的关注,又在一定程度上使得近似值与精确计算值很接近,不损失精度。
算法过程如下:
对LightGBM的一点理解_第1张图片

EFB

EFB主要是从列采样的角度。但并不是真正的采样,因为它降低了列向量的维度,但并不是通过采样的方式得到的,而是通过对feature也构建直方图,然后合并那些exclusive的特征,从而达到减少列向量的目的。
这里有两个关键问题:

  • 如何确定哪些特征需要bundle?
  • 如何bundle?
    它的前提假设是说通常高维的数据往往也是稀疏的,在稀疏的特征空间中,许多特征之间通常是互斥的,可以将这些特征合并成一个特征
    算法流程如下:
    对LightGBM的一点理解_第2张图片

其他

看LightGBM的Github,有提到它是一种带深度限制的Leaf-wise的叶子生长策略(在论文里死活也没找到····),与之相比,XGBoost是一种Level-wise的方式。具体解释是说:

  • Level-wise过一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上Level-wise是一种低效算法,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销,因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。
  • Leaf-wise则是一种更为高效的策略:每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。
  • Leaf-wise的缺点:可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度限制,在保证高效率的同时防止过拟合。
  • 参考这里:1,2

你可能感兴趣的:(machine,learning)