Lightgbm算法

Lightgbm算法

一. 发展过程----why Lightgbm

C 3.0 ( ) > C A R T ( G i n i ) > ( A d a B o o s t ) C3.0(信息增益,信息增益率)->CART(Gini)->提高树(AdaBoost)
> G B D T > X G B o o s t > L i g h t g b m ->GBDT->XGBoost->Lightgbm
CART模型每每过于简单没法有效地进行预测,所以一个更增强力的模型叫作tree ensemble。html

1. AdaBoost算法

AdaBoost是一种提高树的方法,和三个臭皮匠,胜过诸葛亮的道理同样(相似于专家打分)。
AdaBoost两个问题:
(1) 如何改变训练数据的权重或几率分布
提升前一轮被弱分类器错误分类的样本的权重,下降前一轮被分对的权重
(2) 如何将弱分类器组合成一个强分类器,亦即,每一个分类器,前面的权重如何设置
采起”多数表决”的方法.加大分类错误率小的弱分类器的权重,使其做用较大,而减少分类错误率大的弱分类器的权重,使其在表决中起较小的做用。python

2.GBDT算法以及优缺点

GBDT和AdaBosst很相似,可是又有所不一样。
GBDT和其它Boosting算法同样,经过将表现通常的数个模型(一般是深度固定的决策树)组合在一块儿来集成一个表现较好的模型。AdaBoost是经过提高错分数据点的权重来定位模型的不足, Gradient Boosting经过负梯度来识别问题,经过计算负梯度来改进模型,即经过反复地选择一个指向负梯度方向的函数,该算法可被看作在函数空间里对目标函数进行优化。
所以能够说 。 G r a d i e n t B o o s t i n g = G r a d i e n t D e s c e n t + B o o s t i n g Gradient Boosting = Gradient Descent +Boosting
缺点:
GBDT ->预排序方法(pre-sorted)
(1).空间消耗大。这样的算法须要保存数据的特征值,还保存了特征排序的结果(例如排序后的索引,为了后续快速的计算分割点),这里须要消耗训练数据两倍的内存。
(2).时间上也有较大的开销,在遍历每个分割点的时候,都须要进行分裂增益的计算,消耗的代价大。
(3).对cache优化不友好。在预排序后,特征对梯度的访问是一种随机访问,而且不一样的特征访问的顺序不同,没法对cache进行优化。同时,在每一层长树的时候,须要随机访问一个行索引到叶子索引的数组,而且不一样特征访问的顺序也不同,也会形成较大的cache miss。git

3.Why?

经常使用的机器学习算法,例如神经网络等算法,均可以以mini-batch的方式训练,训练数据的大小不会受到内存限制。而GBDT在每一次迭代的时候,都须要遍历整个训练数据屡次。若是把整个训练数据装进内存则会限制训练数据的大小;若是不装进内存,反复地读写训练数据又会消耗很是大的时间。尤为面对工业级海量的数据,普通的GBDT算法是不能知足其需求的。
LightGBM提出的主要缘由就是为了解决GBDT在海量数据遇到的问题,让GBDT能够更好更快地用于工业实践。github

二. 基本介绍

LightGBM is a gradient boosting framework that uses tree based learning algorithms. It is designed to be distributed and efficient with the following advantages:
LightGBM 是一个基于树学习的梯度提高框架,支持高效率的并行训练,它有如下优点:
Faster training speed and higher efficiencyweb

  • 更快的训练效率
    Lower memory usage
  • 低内存使用
    Better accuracy
  • 更好的准确率
    Parallel and GPU learning supported
  • 支持并行和GPU
    Capable of handling large-scale data
  • 可处理大规模数据
    参考: https://github.com/Microsoft/LightGBM
    LightGBM主打的高效并行训练让其性能超越现有其余boosting工具。一个实验代表,在Higgs数据集上LightGBM比XGBoost快将近10倍,内存占用率大约为XGBoost的1/6。

内存占用

三. lighgbm原理

  1. 基于Histogram的决策树算法
  2. 带深度限制的Leaf-wise的叶子生长策略
  3. 直方图作差加速
  4. 直接支持类别特征(Categorical Feature)
  5. Cache命中率优化
  6. 基于直方图的稀疏特征优化
  7. 多线程优化
    下面主要介绍Histogram(直方图)作差加速、带深度限制的Leaf-wise的叶子生长策略。

1.直方图算法

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

这里写图片描述

使用直方图算法有不少优势。首先,最明显就是内存消耗的下降,直方图算法不只不须要额外存储预排序的结果,并且能够只保存特征离散化后的值,而这个值通常用8位整型存储就足够了,内存消耗能够下降为原来的1/8。数组

这里写图片描述

而后在计算上的代价也大幅下降,预排序算法每遍历一个特征值就须要计算一次分裂的增益,而直方图算法只须要计算k次(k能够认为是常数),时间复杂度从O(#data*#feature)优化到O(k*#features)。
固然,Histogram算法并非完美的。因为特征被离散化后,找到的并非很精确的分割点,因此会对结果产生影响。但在不一样的数据集上的结果代表,离散化的分割点对最终的精度影响并非很大,甚至有时候会更好一点。缘由是决策树原本就是弱模型,分割点是否是精确并非过重要;较粗的分割点也有正则化的效果,能够有效地防止过拟合;即便单棵树的训练偏差比精确分割的算法稍大,但在梯度提高(Gradient Boosting)的框架下没有太大的影响。网络

2.Lightgbm 的Histogram(直方图)作差加速

一个容易观察到的现象:一个叶子的直方图能够由它的父亲节点的直方图与它兄弟的直方图作差获得。一般构造直方图,须要遍历该叶子上的全部数据,但直方图作差仅需遍历直方图的k个桶。利用这个方法,LightGBM能够在构造一个叶子的直方图后,能够用很是微小的代价获得它兄弟叶子的直方图,在速度上能够提高一倍。
这里写图片描述多线程

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

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

4.直接支持类别特征

实际上大多数机器学习工具都没法直接支持类别特征,通常须要把类别特征,转化到多维的0/1特征,下降了空间和时间的效率。而类别特征的使用是在实践中很经常使用的。基于这个考虑,LightGBM优化了对类别特征的支持,能够直接输入类别特征,不须要额外的0/1展开。并在决策树算法上增长了类别特征的决策规则。在Expo数据集上的实验,相比0/1展开的方法,训练速度能够加速8倍,而且精度一致。据咱们所知,LightGBM是第一个直接支持类别特征的GBDT工具。
LightGBM的单机版本还有不少其余细节上的优化,好比cache访问优化,多线程优化,稀疏特征优化等等,更多的细节能够查阅Github Wiki(https://github.com/Microsoft/LightGBM/wiki)上的文档说明
这里写图片描述

5.直接支持高效并行

LightGBM还具备支持高效并行的优势。LightGBM原生支持并行学习,目前支持特征并行和数据并行的两种。
特征并行的主要思想是在不一样机器在不一样的特征集合上分别寻找最优的分割点,而后在机器间同步最优的分割点。
数据并行则是让不一样的机器先在本地构造直方图,而后进行全局的合并,最后在合并的直方图上面寻找最优分割点。
LightGBM针对这两种并行方法都作了优化,在特征并行算法中,经过在本地保存所有数据避免对数据切分结果的通讯;在数据并行中使用分散规约 (Reduce scatter) 把直方图合并的任务分摊到不一样的机器,下降通讯和计算,并利用直方图作差,进一步减小了一半的通讯量。
基于投票的数据并行则进一步优化数据并行中的通讯代价,使通讯代价变成常数级别。在数据量很大的时候,使用投票并行能够获得很是好的加速效果。更具体的内容能够看NIPS2016的文章A Communication-Efficient Parallel Algorithm for Decision Tree

这里写图片描述

这里写图片描述

四. LightGBM的参数

LightGBM uses the leaf-wise tree growth algorithm, while many other popular tools use depth-wise tree growth. Compared with depth-wise growth, the leaf-wise algorithm can convenge much faster. However, the leaf-wise growth may be over-fitting if not used with the appropriate parameters.

1参数微调

To get good results using a leaf-wise tree, these are some important parameters:

(1).num_leaves.

This is the main parameter to control the complexity of the tree model. Theoretically, we can set num_leaves = 2^(max_depth) to convert from depth-wise tree. However, this simple conversion is not good in practice. The reason is, when number of leaves are the same, the leaf-wise tree is much deeper than depth-wise tree. As a result, it may be over-fitting. Thus, when trying to tune the num_leaves, we should let it be smaller than 2^
(max_depth).
For example, when the max_depth=6 the depth-wise tree can get good accuracy, but setting num_leaves to 127 may cause over-fitting, and setting it to 70 or 80 may get better accuracy than depth-wise. Actually, the concept depth can be forgotten in leaf-wise tree, since it doesn’t have a correct mapping from leaves to depth.
使用num_leaves
由于LightGBM使用的是leaf-wise的算法,所以在调节树的复杂程度时,使用的是num_leaves而不是max_depth,大体换算关系:num_leaves = 2^(max_depth)

(2).min_data_in_leaf

This is a very important parameter to deal with over-fitting in leaf-wise tree. Its value depends on the number of training data and num_leaves. Setting it to a large value can avoid growing too deep a tree, but may cause under-fitting. In practice, setting it to hundreds or thousands is enough for a large dataset.
(3).max_depth
You also can use max_depth to limit the tree depth explicitly.
(4). 对于非平衡数据集
能够param[‘is_unbalance’]='true’
(5).Bagging参数
bagging_fraction+bagging_freq(必须同时设置)、feature_fraction

2.For Faster Speed

Use bagging by setting bagging_fraction and bagging_freq
Use feature sub-sampling by setting feature_fraction
Use small max_bin
Use save_binary to speed up data loading in future learning
Use parallel learning, refer to Parallel Learning Guide

3.For Better Accuracy

Use large max_bin (may be slower)
Use small learning_rate with large num_iterations
Use large num_leaves (may cause over-fitting)
Use bigger training data
Try dart

4.Deal with Over-fitting

Use small max_bin
Use small num_leaves
Use min_data_in_leaf and min_sum_hessian_in_leaf
Use bagging by set bagging_fraction and bagging_freq
Use feature sub-sampling by set feature_fraction
Use bigger training data
Try lambda_l1, lambda_l2 and min_gain_to_split for regularization
Try max_depth to avoid growing deep tree建模过程(python)

参考文献
[1]https://github.com/Microsoft/LightGBM/blob/master/docs/Features.rst#features
[2]https://lightgbm.readthedocs.io/en/latest/Features.html
[3] http://www.sohu.com/a/123480446_133098