lightgbm

. LightGBM
虽然xgboost在GBDT实现上做了一些改进,但是在数据纬度高,数据量大的情况下依旧不能满足需求。lightGBM主要解决速度问题的,在精度上也做了一点改进。主要从减少数据量和特征量两个角度来提速,针对这两个角度提出了两种新方法:GOSS和EFB。(直方图算法并不是新方法)
(1) GOSS (gradient-based one-side sample)
这里的one-side sample的意思是只对梯度较低的样本集采样,对梯度高的样本全部保留。使用这种技术来减少样本量。主要思想是:如果在某一个样本处的梯度很小,说明该样本对降低损失函数的作用就很低了,所以设置a,b,保留梯度在前num_samplesa的样本,在剩余的样本中采样num_samplesb,而且为了不影响数据分布,这些梯度低的样本在计算增益时需要乘以 。为什么要乘以这个数呢?原本梯度低的样本应该占总样本的(1-a),采样后只占b了,所以需要乘以这个数。
(2) EFB (exclusive feature bundle)
一般高维特征是稀疏的,特征的稀疏性可以近似无损的减少特征数量,EFB就是这样一种技术。
什么是互斥特征?
如果两个特征不同时取非零值,就说这两个特征是互斥的。比如:
lightgbm_第1张图片

为了防止合并之后两个特征的取值一样,feature2加上了feature1的最大值作为偏置。
通过这种方法可以大大减少特征数量。
(3)直方图算法
这其实才是lightGBM速度远超过XGBoost的主要原因,lightGBM的很多并行策略都是基于该算法,而且通过该算法还可以支持类别特征。
直接支持类别特征有什么好处?
如果不直接支持类别特征,需要将类别特征进行编码,如果直接简单的进行数值编码的话,可能为原来无序的类别特征引入序关系;如果进行one-hot编码,当类别特征取值较多时,会使特征维度变得很大,增加计算复杂度,而且树模型本身也不适合将特征进行one-hot 编码,因为one-hot后,每个one-hot特征在进行节点划分时只能按照0或1进行切分,而未one-hot之前切分方式更多,选择增益最大的切分点,one-hot相当于限制了节点的切分方式,可能会使最终学到的树并不是最优的。
lightgbm_第2张图片

由上述算法可以看出,在建立直方图之前,需要先将特征进行分桶,得到每个桶的上边界。因为lightGBM可以直接处理类别特征,所以对连续特征和类别特征分桶的方式是不同的。
连续特征:通过两个参数max_bin(桶的最大数量)和min_data_in_bin(每个桶中数据最小数量)来影响最终生成的桶的上边界数组;通过这个上边界数组就可以知道每个样本属于哪个桶了(二分查找确定)。
类别特征:对于类别特征而言,每个类别特征对应一个桶,不过在分桶之前需要将类别特征按出现次数从大到小进行排序,对出现次数较少的特征不参与分桶。类别特征的桶没有上下界,也没用min_data_in_bin的限制,其返回的是两个字典,{类别:桶编号}和{桶编号:类别},这样就可以将相应的样本映射到对应的桶中,也可以知道每个桶对应的类别。

有上述算法可知,建立直方图的时间复杂度依旧为O(num_samplenum_feature)(这也是贪婪算法寻找分裂特征的时间复杂度),对于每一个特征都需要遍历所有样本来建立该特征的直方图,但是建立直方图后,寻找分裂特征的时间复杂度变为O(num_binnum_feature),大大减少了时间复杂度。

而且lightGBM还采用直方图做差的技巧,进一步减少了时间复杂度。
lightgbm_第3张图片

上述算法计算得分的方式只是其中一种,也可以通过设置is_constant_hessian为False,此时计算得分的方式与XGBoost一样。
(4) 内存优化与并行
XGBoost采用贪婪方法来寻找最优分裂点,那么需要保存每个特征取值排序后的索引及特征值,而基于直方图的算法不需要保存这个索引表,而且只需要保存每个bin的边界值就行了,大大减少了内存占用。
lightgbm_第4张图片

基于直方图的算法可以很容易的进行并行操作,lightGBM主要从三方面进行并行操作:
(1)特征并行
lightgbm_第5张图片

(2)数据并行
lightgbm_第6张图片

(3)投票并行
lightgbm_第7张图片

你可能感兴趣的:(笔记杂)