比XGBOOST更快--LightGBM介绍
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了比XGBOOST更快--LightGBM介绍相关的知识,希望对你有一定的参考价值。
参考技术A xgboost的出现,让数据民工们告别了传统的机器学习算法们:RF、GBM、SVM、LASSO........。现在,微软推出了一个新的boosting框架,想要挑战xgboost的江湖地位。笔者尝试了一下,下面请看来自第一线的报告。包含以下几个部分:
一. 基本介绍
二. XGBOOST原理及缺点
三. LightGBM的优化
四. 建模过程(python)
五. 调参
一. 基本介绍
LightGBM 是一个梯度 boosting 框架,使用基于学习算法的决策树。它可以说是分布式的,高效的,它有以下优势:
- 更快的训练效率
- 低内存使用
- 更好的准确率
- 支持并行学习
- 可处理大规模数据
与常用的机器学习算法进行比较:
· 速度飞起
二. XGBOOST原理及缺点
1. 原理
1 ) 有监督学习
有监督学习的目标函数是下面这个东东:
其中,第一项称为误差函数,常见的误差函数有平方误差,logistic误差等等,第二项称为正则项,常见的有L1正则和L2正则,神经网络里面的dropout等等
2)Boosted Tree
i)基学习器:分类树和回归树(CART)
ii ) Tree Ensemble
一个CART往往过于简单无法有效地预测,因此一个更加强力的模型叫做tree ensemble。
简而言之,Boosted Tree 就是一种 Tree Ensemble的方法,和RF一样,只是构造(学习)模型参数的方法不同。
iii)模型学习:additive training
每一次保留原来的模型不变,加入一个新的函数f到我们的模型中。
f 的选择标准---最小化目标函数!
通过二阶泰勒展开,以及(中间省略N步),我们得到了最终的目标函数:
G、H:与数据点在误差函数上的一阶、二阶导数有关,T:叶子的个数
iv ) 枚举所有不同树结构的贪心算法
不断地枚举不同树的结构,根据目标函数来寻找出一个最优结构的树,加入到我们的模型中,再重复这样的操作。不过枚举所有树结构这个操作不太可行,所以常用的方法是贪心法,每一次尝试去对已有的叶子加入一个分割。对于一个具体的分割方案,我们可以获得的增益可以由如下公式计算。
对于每次扩展,我们还是要枚举所有可能的分割方案,如何高效地枚举所有的分割呢?我假设我们要枚举所有 x
我们可以发现对于所有的a,我们只要做一遍从左到右的扫描就可以枚举出所有分割的梯度和GL和GR。然后用上面的公式计算每个分割方案的分数就可以了。
详细的内容可以看陈天奇大神的文章【3】
2. 缺点
-- 在每一次迭代的时候,都需要遍历整个训练数据多次。如果把整个训练数据装进内存则会限制训练数据的大小;如果不装进内存,反复地读写训练数据又会消耗非常大的时间。
-- 预排序方法(pre-sorted):
首先,空间消耗大。这样的算法需要保存数据的特征值,还保存了特征排序的结果(例如排序后的索引,为了后续快速的计算分割点),这里需要消耗训练数据两倍的内存。
其次,时间上也有较大的开销,在遍历每一个分割点的时候,都需要进行分裂增益的计算,消耗的代价大。
最后,对cache优化不友好。在预排序后,特征对梯度的访问是一种随机访问,并且不同的特征访问的顺序不一样,无法对cache进行优化。同时,在每一层长树的时候,需要随机访问一个行索引到叶子索引的数组,并且不同特征访问的顺序也不一样,也会造成较大的cache miss。
三. LightGBM的优化
基于Histogram的决策树算法
带深度限制的Leaf-wise的叶子生长策略
直方图做差加速
直接支持类别特征(Categorical Feature)
Cache命中率优化
基于直方图的稀疏特征优化
多线程优化
下面主要介绍Histogram算法、带深度限制的Leaf-wise的叶子生长策略。
>>>>
Histogram算法
直方图算法的基本思想是先把连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图。在遍历数据的时候,根据离散化后的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。
图:直方图算法
>>>>
带深度限制的Leaf-wise的叶子生长策略
Level-wise过一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上Level-wise是一种低效的算法,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销,因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。
Leaf-wise则是一种更为高效的策略,每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。Leaf-wise的缺点是可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。
四. 建模过程(python)
数据导入
# 接受:libsvm/tsv/csv 、Numpy 2D array、pandas object(dataframe)、LightGBM binary file
# 需要指定 feature names and categorical features
train_data = lgb.Dataset(dtrain[predictors],label=dtrain[target],feature_name=list(dtrain[predictors].columns), categorical_feature=dummies)
test_data = lgb.Dataset(dtest[predictors],label=dtest[target],feature_name=list(dtest[predictors].columns), categorical_feature=dummies)
设置参数
param = 'max_depth':6,'num_leaves':64,'learning_rate':0.03,'scale_pos_weight':1,'num_threads':40,'objective':'binary','bagging_fraction':0.7,'bagging_freq':1,'min_sum_hessian_in_leaf':100
param['is_unbalance']='true'
param['metric'] = 'auc'
3. CV
bst=lgb.cv(param,train_data,num_boost_round=1000,nfold=3,early_stopping_rounds=30)
estimators = lgb.train(param,train_data,num_boost_round=len(bst['auc-mean']))
4. 预测
ypred = estimators.predict(dtest[predictors])
四. 实测效果
试了一下90W条记录*130维的样本,num_threads设置为40
时间:
2. 准确率:
五. 调参
1. 使用num_leaves
因为LightGBM使用的是leaf-wise的算法,因此在调节树的复杂程度时,使用的是num_leaves而不是max_depth
大致换算关系:num_leaves = 2^(max_depth)
2.对于非平衡数据集:可以param['is_unbalance']='true’
3. Bagging参数:bagging_fraction+bagging_freq(必须同时设置)、feature_fraction
4. min_data_in_leaf、min_sum_hessian_in_leaf
参考文献
https://github.com/Microsoft/LightGBM/
关于LightGBM: http://mp.weixin.qq.com/s?__biz=MzA3MzI4MjgzMw==&mid=2650719786&idx=3&sn=ab1c5a77237dc4b2ee5ae12c7a68ff87&chksm=871b0254b06c8b42d5a4fdf3327f7284c9ffbe72fe7911301d368b157024b32923d88401c2a8&scene=0&open_source=weibo_search
关于XGBOOST:http://www.52cs.org/?p=429
对数据感兴趣的小伙伴,欢迎交流,微信公共号:一白侃数
以上是关于比XGBOOST更快--LightGBM介绍的主要内容,如果未能解决你的问题,请参考以下文章
NGBoost美国斯坦福大学团队算法介绍-作者亲测性能对比LightGBM,XGBoost,catboost
史诗级干货长文集成学习进阶(XGBoost & lightGBM)
推荐算法与量化交易-A-5-5:XGBoost-lightGBM“集成提升树模型”算法-基于模型算法
2020新书企业级机器学习: Spark XGBoost LightGBM, NLP, Keras深度学习, 367页pdf