Skip to content
This repository has been archived by the owner on Sep 12, 2024. It is now read-only.

Latest commit

 

History

History
152 lines (96 loc) · 13.1 KB

File metadata and controls

152 lines (96 loc) · 13.1 KB

【Task4 LightGBM算法梳理】(3days)

1. LightGBM

LightGBM是一个梯度Boosting框架,使用基于决策树的学习算法。它可以说是分布式的,高效的,有以下优势:

  1)更快的训练效率

  2)低内存使用

  3)更高的准确率

  4)支持并行化学习

  5)可以处理大规模数据

2. LightGBM的起源

C3.0(信息增益,信息增益率)−>CART(Gini)−>提升树(AdaBoost)−>GBDT−>XGBoost−>Lightgbm

传统的boosting算法(如GBDT和XGBoost)已经有相当好的效率,但是在如今的大样本和高维度的环境下,传统的boosting似乎在效率和可扩展性上不能满足现在的需求了,主要的原因就是传统的boosting算法需要对每一个特征都要扫描所有的样本点来选择最好的切分点,这是非常的耗时。为了解决这种在大样本高纬度数据的环境下耗时的问题,出现了Lightgbm 。

Lightgbm使用了如下两种解决办法:一是GOSS(Gradient-based One-Side Sampling, 基于梯度的单边采样),不是使用所用的样本点来计算梯度,而是对样本进行采样来计算梯度;二是EFB(Exclusive Feature Bundling, 互斥特征捆绑) ,这里不是使用所有的特征来进行扫描获得最佳的切分点,而是将某些特征进行捆绑在一起来降低特征的维度,是寻找最佳切分点的消耗减少。这样大大的降低的处理样本的时间复杂度,但在精度上,通过大量的实验证明,在某些数据集上使用Lightgbm并不损失精度,甚至有时还会提升精度。

3. Histogram VS pre-sorted

3.1.优势

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 算法的话,通信代价是非常大的(几乎是没办法用的)。所以 xgoobst 在并行的时候也使用 histogram 进行通信。 (数据并行的优化是Lightgbm的令一个亮点,这里不是特别理解,需要再深入研究)

3.2.劣势

histogram 算法不能找到很精确的分割点,训练误差没有 pre-sorted 好。但从实验结果来看, histogram 算法在测试集的误差和 pre-sorted 算法差异并不是很大,甚至有时候效果更好。实际上可能决策树对于分割点的精确程度并不太敏感,而且较“粗”的分割点也自带正则化的效果,再加上boosting算法本身就是弱分类器的集成。

4. leaf-wise VS level-wise

直方图算法的基本思想:先把连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图。遍历数据时,根据离散化后的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。

带深度限制的Leaf-wise的叶子生长策略

Level-wise过一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上Level-wise是一种低效算法,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销,因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。

Leaf-wise则是一种更为高效的策略:每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。

Leaf-wise的缺点:可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度限制,在保证高效率的同时防止过拟合。

5. 特征并行和数据并行

5.1.特征并行

1.1传统算法的的特征并行

传统的特征并行算法旨在于在并行化决策树中的寻找最佳切分点,主要流程如下:

(1)垂直切分数据(不同的Worker有不同的特征集);

(2)在本地特征集寻找最佳切分点 {特征, 阈值};

(3)在各个机器之间进行通信,拿出自己的最佳切分点,然后从所有的最佳切分点中推举出一个最好的切分点,作为全局的切分点;

(4)以最佳划分方法对数据进行划分,并将数据划分结果传递给其他Worker;

(5)其他Worker对接受到的数据进一步划分。

1.2 传统的特征并行方法主要不足:

(1)存在计算上的局限,传统特征并行无法加速特征切分(时间复杂度为 )。 因此,当数据量很大的时候,难以加速。

(2)需要对划分的结果进行通信整合,其额外的时间复杂度约为。(一个数据一个字节)

1.3 LightGBM 中的特征并行

在数据量很大时,传统并行方法无法有效地对特征进行并行,LightGBM 做了一些改变:不再垂直划分数据,即每个Worker都持有全部数据。 因此,LighetGBM中没有数据划分结果之间通信的开销,各个Worker都知道如何划分数据。 而且,样本量也不会变得更大,所以,使每个机器都持有全部数据是合理的。

LightGBM 中特征并行的流程如下:

(1)每个Worker都在本地特征集上寻找最佳划分点{特征, 阈值};

(2)本地进行各个划分的通信整合并得到最佳划分;

(3)执行最佳划分。

然而,该特征并行算法在数据量很大时仍然存在计算上的局限。因此,建议在数据量很大时使用数据并行。

5.2.数据并行

2.1 传统的数据并行算法 数据并行目的是并行化整个决策学习过程。数据并行的主要流程如下:

(1)水平划分数据;

(2)Worker以本地数据构建本地直方图;

(3)将所有Worker的本地直方图整合成全局整合图;

(4)在全局直方图中寻找最佳切分,然后执行此切分。

2.2 传统数据并行的不足: 高通讯开销。 如果使用点对点的通讯算法,一个Worker的通讯开销大约为。 如果使用集体通讯算法(例如, “All Reduce”等),通讯开销大约为。

2.3 LightGBM中的数据并行 LightGBM 中通过减少数据并行过程中的通讯开销,来减少数据并行的开销:

(1)不同于传统数据并行算法中的,整合所有本地直方图以形成全局直方图的方式,LightGBM 使用Reduce scatter的方式对不同Worker的不同特征(不重叠的)进行整合。 然后Worker从本地整合直方图中寻找最佳划分并同步到全局的最佳划分中。

(2)如上面提到的,LightGBM 通过直方图做差法加速训练。 基于此,我们可以进行单叶子的直方图通讯,并且在相邻直方图上使用做差法。 通过上述方法,LightGBM 将数据并行中的通讯开销减少到。

6. 顺序访问梯度

预排序算法中有两个频繁的操作会导致cache-miss,也就是缓存消失(对速度的影响很大,特别是数据量很大的时候,顺序访问比随机访问的速度快4倍以上 )。

对梯度的访问:在计算增益的时候需要利用梯度,对于不同的特征,访问梯度的顺序是不一样的,并且是随机的 对于索引表的访问:预排序算法使用了行号和叶子节点号的索引表,防止数据切分的时候对所有的特征进行切分。同访问梯度一样,所有的特征都要通过访问这个索引表来索引。 这两个操作都是随机的访问,会给系统性能带来非常大的下降。

LightGBM使用的直方图算法能很好的解决这类问题。首先。对梯度的访问,因为不用对特征进行排序,同时,所有的特征都用同样的方式来访问,所以只需要对梯度访问的顺序进行重新排序,所有的特征都能连续的访问梯度。并且直方图算法不需要把数据id到叶子节点号上(不需要这个索引表,没有这个缓存消失问题)


7. 支持类别特征

传统的机器学习一般不能支持直接输入类别特征,需要先转化成多维的0-1特征,这样无论在空间上还是时间上效率都不高。LightGBM通过更改决策树算法的决策规则,直接原生支持类别特征,不需要转化,提高了近8倍的速度。

8. 应用场景

LightGBM是一个性能高度优化的GBTD算法。LightGBM采用了GOSS算法对训练样本集的采样进行了优化,减少了计算梯度时的样本点;同时采用EFB算法,绑定互斥特征,降低选择分裂点时的特征维度。采用了直方图算法和按叶子节点生长的树生成策略。在GOSS和EFB算法的帮助下,使LightGBM在处理大训练样本和高维特征的场景时,在计算速度和内存消耗上明显的优于XGBoost。

9. sklearn参数

(1) 使用num_leaves 因为LightGBM使用的是leaf-wise的算法,因此在调节树的复杂程度时,使用的是num_leaves而不是max_depth。 大致换算关系:num_leaves = 2(max_depth)。它的值的设置应该小于2(max_depth),否则可能会导致过拟合。 (2)对于非平衡数据集:可以param[‘is_unbalance’]='true’ (3)Bagging参数:bagging_fraction+bagging_freq(必须同时设置)、feature_fraction。bagging_fraction可以使bagging的更快的运行出结果,feature_fraction设置在每次迭代中使用特征的比例。 (4) min_data_in_leaf:这也是一个比较重要的参数,调大它的值可以防止过拟合,它的值通常设置的比较大。 (5)max_bin:调小max_bin的值可以提高模型训练速度,调大它的值和调大num_leaves起到的效果类似。

10. CatBoost(了解)

GBDT模型 VS XGBoost模型 VS LightGBM模型

可以应用一般的损失函数,可以处理分类问题和回归问题,常见应用场景比如网页搜索排序、社会生态学等。 优点:a、能够直接处理混合类型的特征; b、对输出空间的异常值的鲁棒性(通过鲁邦的损失函数) 缺点:难以并行,因为本身boosting的思想是一个接一个的训练基学习器

XGBoost模型: 可以使用两种方式防止过拟合:a、直接控制模型复杂度;b、给模型训练增加随机性使其对噪声数据更加鲁棒

LightGBM模型 特点:a、效率和内存上的提升,直方图算法,LightGBM提供一种数据类型的封装相对Numpy, Pandas,Array等数据对象而言节省了内存的使用,原因在于它只需要保存离散的直方图。b、稀疏特征优化,对稀疏特征构建直方图时的时间复杂度为O(2*#非零数据)。c、准确率上的优化

三种模型对比 GBDT无明显的正则化,仅使用了目标函数一阶泰勒展开。 XGBoost使用了目标函数的二阶泰勒展开式(一加快了收敛速度,二本身模型训练的学习率shrinkage可以通过二阶导数做一个逼近),加入了列采样;对缺失值的处理;通过预排序的方法来实现特征并行,提高模型训练效率;XGBoost在选择最佳切分点时可以开启多线程进行,大大提高了运行速度;支持分布式。 LightGBM实现并行方式是通过直方图算法与XGBoost(预排序方式)不同

参考

西瓜书

cs229吴恩达机器学习课程

李航统计学习

谷歌搜索

公式推导参考:http://t.cn/EJ4F9Q0

参考答案