LightGBM 的优点(相较于XGBoost) + 细节操作 讲解 (一)

        GBDT有两种工业化实现 :XGBoost LightGBMLightGBM 是在 XGBoost 的基础之上的优化版本。

        这里是LightGBM优势讲解第一篇,主要包含XGB的缺陷LightGBM的优势,以及LightGBM中基于直方图的决策树最优分割点选取 + Leaf-wise叶子节点生成策略

1. XGBoost 基本缺陷

      XGBoost 是基于预排序的决策树算法。假设正在构建第 T 颗决策树,此时正在构建第 L 层,正在选择第 L 层中第 J 个叶子节点的最佳特征 + 最佳分割点时,有如下步骤:

        (1)分别对所有特征,按照特征的数值进行排序(需要记录排序后的样本索引);

        (2)在遍历最佳分割点时,枚举每一个特征的每一个数值,选择增益最大的分割位置作为最佳分割点;注意:由XGB增益的计算公式可得,增益与第 J 个节点中所有样本的一阶导数 和 二阶导数有关,这些导数值在第 J 个节点确定的时(在上一轮子树划分后,包含的样本都是确定的)都是已知的,可以提前计算好!增益的计算和损失函数的解析解也有关联(如果感兴趣的小伙伴可以自己搜索一下,或者等我写一写);

Gain = \frac{​{G_{L}}^{2}}{H_{L} + \lambda } + \frac{​{G_{R}}^{2}}{H_{R} + \lambda } - \frac{​{G_{}}^{2}}{H_{} + \lambda }

        (3)找到某个特征的最优分割点后,将第 J 个节点的样本分裂成左右子树。

缺点如下

        (1)空间消耗大:需要保存每个样本的特征值 + 特征排序的结果(如索引 + 一阶导数 + 二阶导数结果)

        (2)时间消耗大:枚举每一个分割点时,在使用当前点划分左右子树后,都需要计算左右子树的增益,求得增益Gain。其中 GL 是属于左子树的样本的一阶导数平方和;HL 是属于左子树的样本的二阶导数和,G 是不划分左右子树时候,第 J 个节点自身的一阶导数平方和(在第L - 1层叶子结点划分时计算好了)。

Gain = \frac{​{G_{L}}^{2}}{H_{L} + \lambda } + \frac{​{G_{R}}^{2}}{H_{R} + \lambda } - \frac{​{G_{}}^{2}}{H_{} + \lambda }

        (3)缓存访问效率低:在XGB中,除了存储特征值,还需要存储一个指针,指针从特征值指向样本索引,作用是在选取最优分割点的时候,根据特征值对应的样本索引获取梯度统计值(一阶和二阶梯度值),进而计算增益。此时,特征值有序,但对应的梯度统计值无序,且在存储上并不连续,CPU会不断地访问非连续的内存单元,增加CPU负担提升缓存丢失的几率

        但在 histogram 算法里,不同特征访问梯度的顺序是一样的,可以提前把梯度存在连续的数组中,让不同特征访问的时候都是连续的,不会产生cache miss的问题。

2. LightGBM 基于上述缺陷的优化

(1)基于Histogram(直方图)的决策树算法,主要用于加速分割点的选取;

(2)带深度限制的Leaf-wise的叶子生长策略(XGB使用的是 Level - wise);

(3)单边梯度采样 Gradient-based One-Side Sampling (GOSS);

(4)互斥特征捆绑 Exclusive Feature Bundling (EFB);

(5)直接支持类别特征(Categorical Feature);

(6)支持高效并行;

(7)Cache命中率优化。

3. 每一项优化点的具体操作

3.1 基于直方图的决策树算法

        直方图算法在LightGBM中有两种应用:

        3.1.1 第一种应用:分桶,将连续型特征的特征值,离散化成 K 个整数(分桶,bin),并构造宽度为 K 的直方图。在确定了 K 之后,遍历训练数据,将属于某个bin的样本数据更新为bin的值,并统计每个 bin 中的累计统计量。

优点如下

(1)选取最优分割点时,减少决策树节点的分割次数,即计算增益的次数。

        对于每个特征,基于预排序的最优分割点选取算法(pre-sorted)需要对每个特征值都计算一次分割增益,直方图算法只需要计算 K(直方图中的桶数)次。

(2)减少内存消耗(降低了7倍)

        在XGB中,使用pre-sorted算法,使用32位浮点型存储原始特征 和 排序后每个特征值对应的索引,因此需要 (2 * data_num * feature_num * 4 Bytes)的空间;

        相比之下,对每个特征来说,直方图算法只需要存储特征离散化的数值(或者说是bin值),即 k 个,不需要存储特征原始值 和 排序索引,其中 bin值 用uint8(256 bins)一般足够。因此使用的内存空间一般为(data_num * feature_num * 1 Bytes)。

(3)正则化,防止过拟合

        使用 bin值 替代原始数据相当于增加正则化防止过拟合

        虽然连续型特征进行了离散化,找到的并非最精确的最优分割点,但是!决策树本身就是弱模型,分割点是否精确并非特别重要;较粗的分割点也有正则化的效果,可以有效防止过拟合;即使单棵树的训练误差比精确分割的算法稍大,但在梯度提升(Gradient Boosting)的框架下没有太大的影响(拟合上一颗树和真值的残差)。

(4)减少XGB中的缓存丢失问题,同上文 XGBoost 基本缺陷 (3)

        在XGB中,除了存储特征值,还需要存储一个指针,指针从特征值指向样本索引,作用是在选取最优分割点的时候,根据特征值对应的样本索引获取梯度统计值(一阶和二阶梯度值),进而计算增益。此时,特征值有序,但对应的梯度统计值无序,且在存储上并不连续,CPU会不断地访问非连续的内存单元,增加CPU负担提升缓存丢失的几率

        在histogram 算法里,不同特征访问梯度的顺序是一样的,可以提前把梯度存在连续的数组中,让不同特征访问的时候都是连续的,不会产生cache miss的问题。

缺点如下

(1)bin数量 K 的选择至关重要,它决定了正则化的程度,K越少惩罚越严重,欠拟合风险越高。

(2)分桶策略,使数据的细节特征丢失,相似的数据可能被划分到一起,数据之间的差异消失;
 

  第二种应用: 直方图做差加速 

        LightGBM另一个优化是Histogram(直方图)做差加速。一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到,在速度上可以提升一倍

        通常构造直方图时,需要遍历该叶子上的所有样本,但直方图做差仅需遍历直方图的 K 个桶。在实际构建树的过程中,LightGBM可以先计算直方图小的叶子节点,然后利用直方图做差来获得直方图大的叶子节点(大小两个叶子结点的直方图均有 K 个桶,每个桶内样本不重叠),这样就可以用非常微小的代价得到它兄弟叶子的直方图。

        注意:XGBoost 在进行预排序时只考虑非零值进行加速,而 LightGBM 也采用类似策略:只用非零特征构建直方图。

优点如下

(1)数据并行,减少通信开销

        数据并行的基本思路是:让不同的机器先在本地构造直方图,然后进行全局的合并,最后在合并的直方图上面寻找最优分割点。

        LightGBM通过数据并行中使用分散规约 (Reduce scatter) ,把直方图合并的任务分摊到不同的机器,降低通信和计算,且利用直方图做差,进一步减少了一半的通信量

3.2 叶子生长策略 or 树构建方式

        XGBoost:第 L 层所有节点无差别分裂,但是有些节点分裂增益非常小,引出不必要开销(虽然有根据增益大小的剪枝操作,但仍然需要计算分裂后的结果,因此计算开销不可避免)(需要选择每个叶子结点最优特征 + 最优分割点)。

        LightGBM:当分裂到第 L 层,在 L 层所有叶子结点中选分裂收益最大的节点进行(一层只有一个叶子结点可以分裂,意味着需要选择最优特征 + 最优分割点 + 增益最大叶子结点 );这样的分裂策略易于过拟合,因此需要限制树深度;但是其优势是在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。

        最后:下一遍LightGBM将会讲述 单边梯度采样 Gradient-based One-Side Sampling (GOSS) 和 互斥特征捆绑 Exclusive Feature Bundling (EFB)

        本文参考文献:

XGBoost原理详解及系统优化 - 简书

lightgbm模型解读? - 知乎

Kaggle神器LightGBM最全解读!|直方图|算法|特征值|离散化|拟合_网易订阅

决策树(四)| LightGBM深度解析 - 知乎

猜你喜欢

转载自blog.csdn.net/xiao_ling_yun/article/details/129898730