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 这样的条件,对于某个特定的分割a我们要计算a左边和右边的导数和。

我们可以发现对于所有的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)

  1. 数据导入

    # 接受: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)

  2. 设置参数

    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

  1. 时间:

      Train(num_boost_round=100) cv(early_stopping_rounds=30)
    XGBOOST 45s 809s
    LightGBM 11s 129s

2. 准确率:

  Recall Precision
XGBOOST 35% 3.30%
LightGBM 35% 3.10%

五. 调参

1. 使用num_leaves

因为LightGBM使用的是leaf-wise的算法,因此在调节树的复杂程度时,使用的是num_leaves而不是max_depth

大致换算关系:num_leaves = 2^(max_depth)

max_depth num_leaves
1 2
2 4
3 8
7 128
10 1024

2.对于非平衡数据集:可以param['is_unbalance']='true’

3. Bagging参数:bagging_fraction+bagging_freq(必须同时设置)、feature_fraction

4. min_data_in_leaf、min_sum_hessian_in_leaf

参考文献

  1. https://github.com/Microsoft/LightGBM/

  2. 关于LightGBM: http://mp.weixin.qq.com/s?__biz=MzA3MzI4MjgzMw==&mid=2650719786&idx=3&sn=ab1c5a77237dc4b2ee5ae12c7a68ff87&chksm=871b0254b06c8b42d5a4fdf3327f7284c9ffbe72fe7911301d368b157024b32923d88401c2a8&scene=0&open_source=weibo_search

  3. 关于XGBOOST:http://www.52cs.org/?p=429

对数据感兴趣的小伙伴,欢迎交流,微信公共号:一白侃数

比XGBOOST更快--LightGBM介绍的更多相关文章

  1. 比快更快——微软LightGBM

    LightGBM介绍 xgboost是一种优秀的boosting框架,但是在使用过程中,其训练耗时过长,内存占用比较大.微软在2016年推出了另外一种boosting框架--lightgbm,在不降低 ...

  2. QList介绍(QList比QVector更快,这是由它们在内存中的存储方式决定的。QStringList是在QList的基础上针对字符串提供额外的函数。at()操作比操作符[]更快,因为它不需要深度复制)非常实用

    FROM:http://apps.hi.baidu.com/share/detail/33517814 今天做项目时,需要用到QList来存储一组点.为此,我对QList类的说明进行了如下翻译. QL ...

  3. LightGBM介绍及参数调优

    1.LightGBM简介 LightGBM是一个梯度Boosting框架,使用基于决策树的学习算法.它可以说是分布式的,高效的,有以下优势: 1)更快的训练效率 2)低内存使用 3)更高的准确率 4) ...

  4. 精通Web Analytics 2.0 (9) 第七章:失败更快:爆发测试与实验的能量

    精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第七章:失败更快:爆发测试与实验的能量 欢迎来到实验和测试这个棒极了的世界! 如果Web拥有一个超越所有其他渠道的巨大优势,它就 ...

  5. ubuntu 12.04 LTS 如何使用更快的更新源

    装好ubuntu系统后的第一见事就是替换自带的更新源,原因是系统自带的源有些在中国访问不了,可以访问的速度又特别慢.幸好国内的一些公司和大学提供了速度不错的更新源.下面介绍如何使用更快的更新源 方法/ ...

  6. php提供更快的文件下载

    在微博上偶然看到一篇介绍php更快下载文件的方法,其实就是利用web服务器的xsendfile特性,鸟哥的博客中只说了apache的实现方式,我找到了介绍nginx实现方式的文章,整理一下! let' ...

  7. 更快学习 JavaScript 的 6 个思维技巧

    更快学习 JavaScript 的 6 个思维技巧 我们在学习JavaScript,或其他任何编码技能的时候,往往是因为这些拦路虎而裹足不前: 有些概念可能会造成混淆,尤其当你是从其他语言转过来的时候 ...

  8. 让DB2跑得更快——DB2内部解析与性能优化

    让DB2跑得更快——DB2内部解析与性能优化 (DB2数据库领域的精彩强音,DB2技巧精髓的热心分享,资深数据库专家牛新庄.干毅民.成孜论.唐志刚联袂推荐!)  洪烨著 2013年10月出版 定价:7 ...

  9. 【模式匹配】更快的Boyer-Moore算法

    1. 引言 前一篇中介绍了字符串KMP算法,其利用失配时已匹配的字符信息,以确定下一次匹配时模式串的起始位置.本文所要介绍的Boyer-Moore算法是一种比KMP更快的字符串匹配算法,它到底是怎么快 ...

随机推荐

  1. 自己手写一个SpringMVC框架

    前端框架很多,但没有一个框架称霸,后端框架现在Spring已经完成大一统.所以学习Spring是Java程序员的必修课. Spring框架对于Java后端程序员来说再熟悉不过了,以前只知道它用的反射实 ...

  2. Objective C - 2 - 随机数,可变字符串,字符串,SubString

    int main(int argc, const char * argv[]) { @autoreleasepool { NSString *outputString = @"1234567 ...

  3. MySQL 5.7笔记

    1. 初始化 重命名my-default.ini为my.ini 添加character_set_server=utf8 运行mysqld --initialize 2. 重置密码 服务器运行: mys ...

  4. nginx初步尝试

    导师要我学习下nginx,弄个简单的负载均衡出来,具体就是请求发送到nginx上,然后nginx将请求转发到后面的两个jetty应用上,这两个应用的代码是一样的,只是监听的端口不同,由于是简单尝试,因 ...

  5. 利用ajax完成项目图册上传删除【实际项目】

    [项目页面效果] [前台jsp页面] jsp的js代码 <script type="text/javascript"> //上传项目图片 function upload ...

  6. 使用Session防止表单重复提交(不考虑多服务器)

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 原理:  1, ...

  7. Loj 504 ZQC的手办

    Loj 504 ZQC的手办 用线段树维护,每个节点存储区间内最小值 \(val\) 以及最小值出现的一个位置 \(pos\) . 对操作 \(1\) ,只需打标记即可,因为我们不维护其他的信息(如区 ...

  8. 使用python处理selenium中的鼠标悬停问题

    # 导入selenium中的actionchains的方法 from selenium.webdriver.common.action_chains import ActionChains #识别需要 ...

  9. 【DUBBO】dubbo架构详解(转载)

    转载地址:http://shiyanjun.cn/archives/325.html Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解 ...

  10. php基础语法(数据类型、运算符)

    数据类型 标量类型: int, float, string, bool 复合类型: array, object 特殊类型: null, resouce 整数类型int, integer 字符串类型st ...