lightgbm 保存模型 过大_LightGBM优化原理

本文介绍了LightGBM相对于XGB的优化策略,重点讲解了直方图算法如何提高训练速度和减少内存使用。直方图优化包括减少分割增益计算量、直方图作差加速、减少内存使用和并行学习优化。此外,讨论了Leaf-Wise生长策略、类别特征处理、数据并行和投票并行等技术,以及LightGBM在处理数据不均衡和信息增益计算上的方法。
摘要由CSDN通过智能技术生成

442bac926de641b4712e6412c71a42c1.png

0. 直方图优化算法

​ XGB在计算树节点信息增益的时候,使用了预排序的方法来进行节点分裂,这样计算出的分裂节点比较精确,但也造成了很大的时间开销。因此,LightGBM选择了基于直方图的优化算法。

​ 类别特征如何转为直方图:对于分类特征来说,则是每一种取值放入一个bin,且当取值的个数大于max bin数时,会忽略那些很少出现的category值。在节点分裂的时候,这时候就不需要按照预排序算法那样,对于每个特征都计算#data遍了,而是只需要计算#bins遍,这样就大大加快了训练速度。

算法伪代码:

989bf8500e115c61ec6c12dce08dfc2b.png

最外面的 for 循环表示的意思是对当前模型下所有的叶子节点处理,需要遍历所有的特征,来找到增益最大的特征及其划分值,以此来分裂该叶子节点。在某个叶子上,第二个 for 循环就开始遍历所有的特征了。对于每个特征,首先为其创建一个直方图。这个直方图存储了两类信息,分别是每个bin中样本的梯度之和$H[f.bins[i]].g$,还有就是每个bin中样本数量$H[f.bins[i]].n$。第三个 for 循环遍历所有样本,累积上述的两类统计值到样本所属的bin中。即直方图的每个 bin 中包含了一定的样本,在此计算每个 bin 中的样本的梯度之和并对 bin 中的样本记数。

d8b7b6d4867d162cd4d609e4e65143c4.png

1. 性能相关

1.1 减少分割增益计算量

​ 对于XGB,在计算最佳分割点(非近似直方图算法)需要O(#data)次的计算。即计算一个最佳的分裂增益为O(#data*#features)。而对于LGB,直方图算法只需要计算0(#bins*#features)

1.2 直方图作差加速

​ 在二叉树中可以通过利用叶节点的父节点和相邻节点的直方图的相减获得该节点的直方图。所以,仅仅需要为一个叶子节点建立直方图,相邻节点可以通过直方图作差来进行加速。

1.3 减少内存使用

​ 将连续的值替换为discrete bins。若bins足够小,可以利用较小的数据类型来进行存储。比如unit8_t

​ XGB需要对数据进行预排序,需要额外的空间存储特征值到样本的索引信息。

1.4 减少并行学习的通信代价

2. 准确率相关

2.1 Leaf-Wise生长策略

与Level-Wise生长策略作对比

2.2 类别特征的最优分割

3. 并行学习的优化

3.1 特征并行

传统的特征并行算法如下:

  • 垂直划分数据,不同的机器有不同的特征集
  • 在本地特征集中寻找局部的最佳分割点
  • 本地进行各个划分的通信整合并得到最佳的划分
  • 在某个机器X上以最佳的划分对数据进行划分,(需要注意:其他线程或者woker不具有该特征的数据信息,因为特征平均分配在各个worker, 各个worker的特征没有交集)。既然其他机器无法根据选出的特征最佳切分进行划分,那么其他节点怎么划分呢?答案是:在机器X上进行划分后,将划分结果通知给其他机器,这样会增大通信开销。
  • 其他线程或者worker对接收到的数据进行划分。

以上方案缺点:split finding计算复杂度很高为O(data),当数据量很大的时候,非常慢。其次,有很大通信开销。

LightGBM如何解决?LGB让每个线程拥有所有的数据。因此,LightGBM中没有数据划分结果的通信开销,只要知道最佳的分割点,因为每个线程都有所有数据,可以在线程本地进行切分。过程如下:

  • 每个线程都在本地数据集上寻找最佳的分割点(每个线程负责不同的特征的计算)
  • 本地进行各个划分的整合,找到全局的最佳划分
  • 每个节点拿到最佳划分后,执行最佳切分。

注意:该特征并行算法在数据量很大时,每个机器存储所有数据代价很高。因此,在数据量很大时,建议使用数据 并行的策略。

3.2 数据并行

传统的数据并行算法如下:

0eaf358b6a287edfb46568fd9c115519.png
  • 水平划分数据
  • 线程以本地数据构建本地直方图
  • 将本地直方图整合成全局直方图
  • 在全局直方图中寻找最佳划分,然后执行此划分

以上缺点:

​ 高通讯开销。机器合并直方图时,每个机器需要和其他剩下的所有机器通信,整合成全局直方图。那么通信开销为O(#machine*#feature*#data)

​ LightGBM如何解决?不同于整合所有本地直方图以形成全局直方图的方式,LIghtGBM使用分散规约(Reduce Scatter)的方式。将合并直方图的任务分摊到不同的机器,对不同机器的不同特征(不重叠的)进行整合。然后线程从本地整合直方图中寻找最佳划分到并同步到全局最佳的划分中?什么意思呢?举个例子如下:

​ 假设由100个特征,20个worker。每个机器负责5个不同的特征的整合, 并且找出这5个特征的最优划分。然后各个worker从本地整合直方图中寻找最佳划分并同步到全局的最佳划分中。LIghtGBM还使用直方图作差加速,基于此,我们可以进行单叶子的直方图通讯,并且在相邻直方图上使用做差。通信开销减少为O(0.5*#feature*#bin)

​ 总而言之,对某个节点进行划分时,传统的方法需要得到全局的直方图,这时候需要的时间复杂度为:O(#machine*#feature*#data),然后所有worker都能访问这个直方图。LGB每个worker只整合部分特征的直方图,有效减少了每个worker的通信开销,并让整合寻找切分充分并行。

3.3 投票并行

​ 基于投票的并行是对数据并行的优化,数据并行的瓶颈主要在于合并直方图的时候,通信代价比较大。根据这一点,基于投票的并行,用投票的方式只合并部分特征值的直方图,达到了降低通信量的目的。首先,通过本地的数据找到本地的top k best features. 然后利用投票筛选出可能是全局最优分割点的特征,合并直方图的时候只合并这些被选出来的特征,从此降低了通信量。

4. 其他

4.1 LGB解决数据不均衡

scale_pos_weight参数。该参数是什么意思?sample_pos_weight = number of negative samples / number of positive samples

4.2 LGB如何计算信息增益

与XGB类似

4.3 LGB对连续特征与离散特征的处理方式区别

连续特征:首先找到连续特征的bin分割点。然后只需要根据特征取值找到相应的bin即可,使用二分搜索

类别特征:首先对类别特征A,对特征取值按出现次数进行排序。忽略出现次数很少的特征。然后记录每个bin对应什么特征取值,特征取值对应哪个bin一一对应。这样,以后就能很方便的进行bin到特征取值和特征取值到bin的转化。

离散特征构建直方图的过程:

4.4 如何构建直方图

给定一个特征取值,计算得到对应的bin,累加到直方图相应的位置中去。

5. XGB与LGB比较

  • 内存消耗

Pre-sorted 算法需要的内存约是训练数据的两倍(2 * #data * #features 4Bytes),它需要用32位浮点(4Bytes)来保存 feature value,并且对每一列特征,都需要一个额外的排好序的索引,这也需要32位(4Bytes)的存储空间。因此是(2 * #data * #features 4Bytes)。而对于 histogram 算法,则只需要(#data * #features * 1Bytes)的内存消耗,仅为 pre-sorted算法的1/8。因为 histogram 算法仅需要存储 feature bin value (离散化后的数值),不需要原始的 feature value,也不用排序,而 bin value 用 1Bytes(256 bins) 的大小一般也就足够了。

  • 计算速度

计算上的优势则是大幅减少了计算分割点增益的次数。对于每一个特征,pre-sorted 需要对每一个不同特征值都计算一次分割增益,代价是O(#feature#distinct_values_of_the_feature);而 histogram 只需要计算#bins次,代价是(#feature#bins)

  • 缓存命中率

还有一个很重要的点是cache-miss。事实上,cache-miss对速度的影响是特别大的。预排序中有2个操作频繁的地方会造成cache miss,一是对梯度的访问,在计算gain的时候需要利用梯度,不同特征访问梯度的顺序都是不一样的,且是随机的,因此这部分会造成严重的cache-miss。二是对于索引表的访问,预排序使用了一个行号到叶子节点号的索引表(row_idx_to_tree_node_idx ),来防止数据切分时对所有的数据进行切分,即只对该叶子节点上的样本切分。在与level-wise进行结合的时候, 每一个叶子节点都要切分数据,这也是随机的访问。这样会带来严重的系统性能下降。而直方图算法则是天然的cache friendly。在直方图算法的第3个for循环的时候,就已经统计好了每个bin的梯度,因此,在计算gain的时候,只需要对bin进行访问,造成的cache-miss问题会小很多。

  • 数据并行优化上的方案

在数据并行的时候,用 histgoram 可以大幅降低通信代价。用 pre-sorted 算法的话,通信代价是非常大的(几乎是没办法用的,当然XGB也有自己的近似直方图算法)。所以 xgoobst 在并行的时候也使用 histogram 进行通信。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值