[标点符] 初学机器学习算法之LightGBM (直方图+单边梯度采样优化+互斥特征绑定优化)

LightGBM简介

  • 简介
    基于GBDT的梯度提升决策树模型LGB,是GBDT的一种高效实现,可xgb的原理基本一致,主要都采用损失函数梯度下降 方向作为当前决策树的残差近似值,去拟合新的决策树。
  • 优势
    LightGBM具有更快的训练效率, 低内存的使用,支持并行化学习,可以处理大规模(海量)的数据,支持支持使用category特征
  • 速度提升
    实验数据: 比xgb快了将近10倍,内存占用率大约为xgb的1/6,并且准确率也有提升.

xgboost的优缺点

01 xgboost 精确贪心算法

每轮迭代时,都需要遍历整个训练数据多次;需要把整个数据集装进内存中。
优点: 可以找到精确的划分条件
缺点: 计算量巨大,内存占用也巨大,易产生过拟合

02 xgboost Level-wise(水平的)迭代方式

预排序的方法(pre-sorted):首先空间消耗大——保存了预排序后的结果,需要多消耗内存;其次,在遍历每一个分割点的时候,都需要进行分裂增益的计算,消耗的代价大。
优点: 可以使用多线程,可以加速精确的贪心算法!!
缺点:效率低下,会产生不必要的叶子结点;并且,存在大量无用计算

03 XGBoost对cache优化不友好的几点解释

特征对梯度(预排序后的结果)是一种随机访问(顺序访问,在磁盘中是随机访问的定义),并且不同的特征访问的顺序不一样,无法对cache进行优化;
(注:cache在内存中是按页(一块一块)来进行划分的)
想要命中不同的特征的cache,需要进行不同的随机访问;
并且不同特征的访问顺序也不一致,也会造成较大的cache miss

LightGBM相较于xgboost优化了哪些方面

LGB主要设计特征

  1. 基于直方图的决策树算法
  2. 带深度限制的Leaf-wise(按带深度限制的按叶子结点的生成方式)的叶子生成策略
  3. 直方图加速:做差进行加速
  4. Cache 命中率进行优化
  5. 直接支持类别特征(categorical Feature)
  6. 基于直方图的稀疏特征优化
  7. 多线程优化

决策树算法的差异 XGBoost VS LightGBM

决策树算法 -> 改进

XGBoost使用的是pre-sorted算法,能够更精确的找到数据分隔点。(代价:预排序需要两倍的内存,遍历每一个分割点,都需要进行增益计算,慢)
LightGBM使用的是直方图算法,步骤:将连续的浮点特征离散成K个离散值,构造宽度为k的直方图,遍历训练数据,统计每个离散值在直方图中的累计统计量;
在进行选择的时候,只需要根据直方图的离散值,遍历寻找最优的分割点。

LightGBM内存可以降为之前的1/8

之前需要int_32位来进行存储,现在int_8位就可以了

计算代价得到降低

预排序: O(#data#features)。
直方图: k个特征——也就是bin的分箱个数, O(#bin
#features)。

直方图算法的缺陷

直方图算法的思想也很简单,首先将连续的浮点数据转换为bin数据,具体过程是首先确定对于每一个特征需要多少的桶bin,然后均分,将属于该桶的样本数据更新为bin的值,最后用直方图表示。

  1. 使用bins替代了原数据, 相等于增加了正则化** (正则化的值越大,则模型越简单)**
  2. 放弃了部分细节,导致很多数据的细节特征消失了,相似的数据就可能会被分到同一个桶内
  3. bin数量选择决定了正则化的程度,bin分箱数目越少,模型越简单,越容易欠拟合。

直方图算法需要注意的地方:

  • 构建直方图时不需要对数据进行排序(比XGBoost快),因为预先设定了bin的范围;
  • 直方图除了保存划分阈值和当前bin内样本数以外还保存了当前bin内所有样本的一阶梯度和(一阶梯度和的平方的均值等价于均方损失);
  • 阈值的选取是按照直方图从小到大遍历,使用了上面的一阶梯度和,目的是得到划分之后△loss最大的特征及阈值。

Histogram 算法的优缺点:

  • Histogram算法并不是完美的。由于特征被离散化后,找到的并不是很精确的分割点,所以会对结果产生影响。但在实际的数据集上表明,离散化的分裂点对最终的精度影响并不大,甚至会好一些。原因在于decision tree本身就是一个弱学习器,采用Histogram算法会起到正则化的效果,有效地防止模型的过拟合。
  • 时间上的开销由原来的O(#data * #features)降到O(k * #features)。由于离散化,#bin远小于#data,因此时间上有很大的提升。

Histogram算法还可以进一步加速

一个叶子节点的Histogram可以直接由父节点的Histogram和兄弟节点的Histogram做差得到。
一般情况下,构造Histogram需要遍历该叶子上的所有数据,通过该方法,只需要遍历Histogram的k个桶即可。速度提升了一倍。

决策树生长策略

  • 进一步优化,不再使用按层生成的算法,而是按带深度限制的按叶子结点的生成方式
  • XGBoost采用的是按层生长level(depth)-wise生长策略,能够同时分裂同一层的叶子,从而进行多线程优化,不容易过拟合;但不加区分的对待同一层的叶子,带来了很多没必要的开销。因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。
  • LightGBM采用leaf-wise生长策略,每次从当前所有叶子中找到分裂增益最大(一般也是数据量最大)的一个叶子,然后分裂,如此循环。因此同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。Leaf-wise的缺点是可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。

直方图差加速

  • LightGBM另一个优化是Histogram(直方图)做差加速。
    一个容易观察到的现象:一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到。
    通常构造直方图,需要遍历该叶子上的所有数据,但直方图做差仅需遍历直方图的k个桶。
    利用这个方法,LightGBM可以在构造一个叶子的直方图后,可以用非常微小的代价得到它兄弟叶子的直方图,在速度上可以提升一倍。

直接支持类别特征

  • 常规:实际上大多数机器学习工具都无法直接支持类别特征,一般需要把类别特征,转化one-hotting特征,降低了空间和时间的效率
  • LGB:LightGBM优化了对类别特征的支持,可以直接输入类别特征,不需要额外的0/1展开;lgb还在决策树算法上增加了类别特征的决策规则。

one-hot编码是处理类别特征的一个通用方法,然而在树模型中,这可能并不一定是一个好的方法,尤其当类别特征中类别个数很多的情况下。主要的问题是:

  • 浪费:可能存在浪费了某一个特征,使用ine-hot编码后,在每一个决策结点上,要么选择这个枚举的特征值或者不选择。
  • 切分收益很低:当类别值很多时,每个类别上的数据可能会比较少,这时候切分会产生不平衡,这意味着切分增益也会很小(比较直观的理解是,不平衡的切分和不切分没有区别)。
  • 会影响决策树的学习。决策树学习时利用的是统计信息,在这些数据量小的空间上,统计信息不准确,学习会变差。

LGB支持求解类别特征的最优切分的流程

  • 离散特征建立直方图:统计、排序、过滤、bins容器
  • 计算分裂阈值的过程:
    - 先看该特征下划分出的bin容器的个数,少的话(4个以下),直接逐个扫描
    - 对于bin容器较多的情况, 先进行过滤,只让子集合较大的bin容器参加划分阈值计算, 对每一个符合条件的bin容器进行公式计算(公式如下: 该bin容器下所有样本的一阶梯度之和/该bin容器下所有样本的二阶梯度之和 + 正则项(参数cat_smooth),得到一个值,根据该值对bin容器从小到大进行排序,然后分从左到右、从右到左进行搜索,得到最优分裂阈值。
    - LightGBM中对离散特征实行的是many vs many 策略,这32个bin中最优划分的阈值的左边或者右边所有的bin容器就是一个many集合,而其他的bin容器就是另一个many集合。
    - 对于连续特征,划分阈值只有一个,对于离散值可能会有多个划分阈值,每一个划分阈值对应着一个bin容器编号,当使用离散特征进行分裂时,只要数据样本对应的bin容器编号在这些阈值对应的bin集合之中,这条数据就加入分裂后的左子树,否则加入分裂后的右子树。

LGB直接支持高效并行

  • 支持特征并行:是在不同机器在不同的特征集合上分别寻找最优的分割点,然后在机器间同步最优的分割点
    - 通过在本地保存全部数据避免对数据切分结果的通信
  • 支持数据并行:让不同的机器先在本地构造直方图,然后进行全局的合并,最后在合并的直方图上面寻找最优分割点。
    - 使用分散规约(Reduce scatter)把直方图合并的任务分摊到不同的机器,降低通信和计算,并利用直方图做差,进一步减少了一半的通信量。

网络通信优化

XGBoost由于采用pre-sorted算法,通信代价非常大,所以在并行的时候也是采用histogram算法;LightGBM采用的histogram算法通信代价小,通过使用集合通信算法,能够实现并行计算的线性加速。

LightGBM原理

论文地址:LightGBM A Highly Efficient Gradient Boosting (https://papers.nips.cc/paper/6907-lightgbm-a-highly-efficient-gradient-boosting-decision-tree.pdf)

对比:

普通的GBDT、XGB:信息增益、预排序,计算信息增益需要扫描所有样本,从而找到最优划分点。在面对大量数据或者特征维度很高时,它们的效率和扩展性很难使人满意。

微软开源的LightGBM(基于GBDT的)包含两个算法:

  • 单边梯度采样,Gradient-based One-Side Sampling(GOSS)
    - GOSS(从减少样本角度):排除大部分小梯度的样本,仅用剩下的样本计算信息增益。
    - 梯度大的实例对信息增益有更大的影响,因此在下采样时,我们应该尽量保留梯度大的样本(预先设定阈值,或者最高百分位间),随机去掉梯度小的样本。
  • 互斥特征绑定,Exclusive Feature Bundling(EFB)
    - 捆绑互斥特征,也就是他们很少同时取非零值(也就是用一个合成特征代替)。通常真是应用中,虽然特征量比较多,但是由于特征空间十分稀疏,是否可以设计一种无损的方法来减少有效特征呢?特别在稀疏特征空间上,许多特征几乎是互斥的(例如许多特征不会同时为非零值,像one-hot),我们可以捆绑互斥的特征。最后,我们将捆绑问题归约到图着色问题,通过贪心算法求得近似解。
    - EBF的算法步骤如下:
    - 将特征按照非零值的个数进行排序
    - 计算不同特征之间的冲突比率
    - 遍历每个特征并尝试合并特征,使冲突比率最小化

如何使用LightGBM

LightGBM调参指导

针对 leaf-wise 树的参数优化:

  • num_leaves:控制了叶节点的数目。它是控制树模型复杂度的主要参数。
  • 如果是level-wise,则该参数为2depth,其中depth为树的深度。但是当叶子数量相同时,leaf-wise的树要远远深过level-wise树,非常容易导致过拟合。因此应该让num_leaves小于2depth。在leaf-wise树中,并不存在depth的概念。因为不存在一个从leaves到depth的合理映射。
  • min_data_in_leaf:每个叶节点的最少样本数量。它是处理leaf-wise树的过拟合的重要参数。将它设为较大的值,可以避免生成一个过深的树。但是也可能导致欠拟合。
  • max_depth: 控制了树的最大深度。该参数可以显式的限制树的深度。

针对更快的训练速度:

  • 通过设置 bagging_fraction 和 bagging_freq 参数来使用 bagging 方法
  • 通过设置 feature_fraction 参数来使用特征的子抽样
  • 使用较小的 max_bin
  • 使用 save_binary 在未来的学习过程对数据加载进行加速

获取更好的准确率:

  • 使用较大的 max_bin (学习速度可能变慢)
  • 使用较小的 learning_rate 和较大的 num_iterations
  • 使用较大的 num_leaves (可能导致过拟合)
  • 使用更大的训练数据
  • 尝试 dart

缓解过拟合:

  • 使用较小的 max_bin
  • 使用较小的 num_leaves
  • 使用 min_data_in_leaf 和 min_sum_hessian_in_leaf
  • 通过设置 bagging_fraction 和 bagging_freq 来使用 bagging
  • 通过设置 feature_fraction 来使用特征子抽样
  • 使用更大的训练数据
  • 使用 lambda_l1, lambda_l2 和 min_gain_to_split 来使用正则
  • 尝试 max_depth 来避免生成过深的树

参考链接:

posted @ 2020-12-27 18:17  山枫叶纷飞  阅读(2137)  评论(0编辑  收藏  举报