LightGBM

2018/06/08 机器学习

LightGBM

数据接口

要加载ligsvm文本文件或LightGBM二进制文件到Dataset中:train_data = lgb.Dataset(‘train.svm.bin’)

要加载numpy数组到Dataset中:train_data = lgb.Dataset(data, label=label)

创建验证数据:test_data = train_data.create_valid(‘test.svm’) 或者 test_data = lgb.Dataset(‘test.svm’, reference=train_data)。在LightGBM中,验证数据应该与训练数据一致(格式一致)。

指定feature names(特征名称)和categorical features(分类特征):train_data = lgb.Dataset(data, label=label, feature_name=[‘c1’, ‘c2’, ‘c3’], categorical_feature=[‘c3’])。在你构造Dataset之前, 你应该将分类特征转换为int类型的值

设置参数

LightGBM可以使用一个pairs的list或一个字典来设置参数。

训练

训练模型。param是参数列表,train_data是训练集,valid_sets是验证集。

num_round = 10
bst = lgb.train(param, train_data, num_round, valid_sets=[test_data]) 

在训练完成后,可以使用如下方式来存储模型:

bst.save_model('model.txt')

训练后的模型也可以转存为JSON的格式:

json_model = bst.dump_model()

已保存模型也可以使用如下的方式来加载。

bst = lgb.Booster(model_file='model.txt')  #init model

交叉验证

使用5-折方式的交叉验证来进行训练(4个训练集,1个测试集):

num_round = 10
lgb.cv(param, train_data, num_round, nfold=5)

提前停止

如果您有一个验证集,你可以使用提前停止找到最佳数量的boosting rounds(梯度次数)。提前停止需要在valid_sets中至少有一个集合。如果有多个,它们都会被使用:

bst = lgb.train(param, train_data, num_round, valid_sets=valid_sets, early_stopping_rounds=10)
bst.save_model('model.txt', num_iteration=bst.best_iteration)

该模型将开始训练,直到验证得分停止提高为止。验证错误需要至少每个early_stopping_rounds减少以继续训练。

如果提前停止,模型将有1个额外的字段:bst.best_iteration。请注意train()将从最后一次迭代中返回一个模型,而不是最好的一个。

预测

已经训练或加载的模型都可以对数据集进行预测:

如下为7个样本,每一个包含10个特征。
data = np.random.rand(7, 10)
ypred = bst.predict(data)

如果在训练过程中启用了提前停止,可以用 bst.best_iteration从最佳迭代中获得预测结果:

ypred = bst.predict(data, num_iteration=bst.best_iteration)

XGBoost vs. LightGBM

  • 树的切分策略不同。XGBoost是level-wise而LightGBM是leaf-wise。level-wise过一次数据可以同时分裂同一层的叶子,容易进行多线程优化,不容易过拟合。但实际上level-wise是一种低效的算法,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销。因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。leaf-wise则是一种更为高效的策略,每次从当前所有叶子中,找到分裂增益最大(一般也是数据量最大)的一个叶子,然后分裂,如此循环。因此同level-wise相比,在分裂次数相同的情况下,leaf-wise 可以降低更多的误差,得到更好的精度。leaf-wise 的缺点是可能会长出比较深的决策树,产生过拟合。因此LightGBM在leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。
  • 实现并行的方式不同。XGBoost是通过预排序的方式;LightGBM则是通过直方图算法。使用直方图简化计算,计算split时只考虑直方图的bin做划分点,而不细化到每个sample。计算直方图时,两个子节点只用计算其中一个,另一个通过root和前一个做差可得。基于histogram的算法,在寻找最佳split时,可以先顺序访问data的gradient,填入对应bin中,提高cache hit。
  • LightGBM直接支持类别特征,对类别特征不必进行独热编码处理。类别特征的进一步优化,不再使用类似one-hot编码的分割方式。对于类别数量很多的类别特征,使用one-vs-other的切分方式会长出很不平衡的树,不能实现较好的精度。这是树模型在支持类别特征的一个痛点。LightGBM可以找出类别特征的最优切割,即many-vs-many的切分方式。并且最优分割的查找的时间复杂度可以在线性时间完成,和原来的one-vs-other的复杂度几乎一致。

建直方图的过程如下:

  • 首先对原数据排序;
  • 然后统计出distinct value以及对应的count;
  • 如果distinct value数目小于max bin数,则正好每个value放入一个bin;
  • 如果distinct value大于max bin,计算bin大小的均值,按一定规则将sample放入bin,保证相同value的放入同一bin,bin包含的sample数尽量平均。注:max bin的默认值是256。
  • 对于category类型的feature,则是每一种取值放入一个bin,且当取值的个数大于max bin数时,会忽略那些很少出现的category值。
  • 在求split时,对于category类型的feature,算的是”按是否属于某个category值划分”的gain,这和数值型feature是完全不同的,它的实际效果就是类似one-hot的编码方法。

参考

LightGBM的英文文档

LightGBM的中文文档

LightGBM原理之论文详解

开源 微软开源GB框架LightGBM,表现超越已有boosting工具

比XGBOOST更快–LightGBM介绍(Histogram算法、带深度限制的Leaf-wise的叶子生长策略)

如何看待微软新开源的LightGBM?

浅谈决策树、GBDT、LightGBM

Search

    Table of Contents