xgboost: 速度快效果好的boosting模型

xgboost: 速度快效果好的boosting模型

Python R

本文作者:何通,SupStat Inc(总部在纽约,中国分部为北京数博思达信息科技有限公司)数据科学家,加拿大Simon Fraser University计算机学院研究生,研究兴趣为数据挖掘和生物信息学。

主页:https://github.com/hetong007

引言

在数据分析的过程中,我们经常需要对数据建模并做预测。在众多的选择中,randomForest,gbmglmnet是三个尤其流行的R包,它们在Kaggle的各大数据挖掘竞赛中的出现频率独占鳌头,被坊间人称为R数据挖掘包中的三驾马车。根据我的个人经验,gbm包比同样是使用树模型的randomForest包占用的内存更少,同时训练速度较快,尤其受到大家的喜爱。在python的机器学习库sklearn里也有GradientBoostingClassifier的存在。

Boosting分类器属于集成学习模型,它基本思想是把成百上千个分类准确率较低的树模型组合起来,成为一个准确率很高的模型。这个模型会不断地迭代,每次迭代就生成一颗新的树。对于如何在每一步生成合理的树,大家提出了很多的方法,我们这里简要介绍由Friedman提出的Gradient Boosting Machine。它在生成每一棵树的时候采用梯度下降的思想,以之前生成的所有树为基础,向着最小化给定目标函数的方向多走一步。在合理的参数设置下,我们往往要生成一定数量的树才能达到令人满意的准确率。在数据集较大较复杂的时候,我们可能需要几千次迭代运算,如果生成一个树模型需要几秒钟,那么这么多迭代的运算耗时,应该能让你专心地想静静……

现在,我们希望能通过xgboost工具更好地解决这个问题。xgboost的全称是eXtreme Gradient Boosting。正如其名,它是Gradient Boosting Machine的一个c++实现,作者为正在华盛顿大学研究机器学习的大牛陈天奇。他在研究中深感自己受制于现有库的计算速度和精度,因此在一年前开始着手搭建xgboost项目,并在去年夏天逐渐成型。xgboost最大的特点在于,它能够自动利用CPU的多线程进行并行,同时在算法上加以改进提高了精度。它的处女秀是Kaggle的希格斯子信号识别竞赛,因为出众的效率与较高的预测准确度在比赛论坛中引起了参赛选手的广泛关注,在1700多支队伍的激烈竞争中占有一席之地。随着它在Kaggle社区知名度的提高,最近也有队伍借助xgboost在比赛中夺得第一

为了方便大家使用,陈天奇将xgboost封装成了python库。我有幸和他合作,制作了xgboost工具的R语言接口,并将其提交到了CRAN上。也有用户将其封装成了julia库。python和R接口的功能一直在不断更新,大家可以通过下文了解大致的功能,然后选择自己最熟悉的语言进行学习。

功能介绍

一、基础功能

首先,我们从github上安装这个包:

devtools::install_github('dmlc/xgboost',subdir='R-package')

动手时间到!第一步,运行下面的代码载入样例数据:

require(xgboost)data(agaricus.train,package='xgboost')data(agaricus.test,package='xgboost')train <- agaricus.traintest <- agaricus.test

这份数据需要我们通过一些蘑菇的若干属性判断这个品种是否有毒。数据以1或0来标记某个属性存在与否,所以样例数据为稀疏矩阵类型:

>class(train$data)[1]"dgCMatrix"attr(,"package")[1]"Matrix"

不用担心,xgboost支持稀疏矩阵作为输入。下面就是训练模型的命令

> bst <- xgboost(data = train$data, label = train$label, max.depth =2, eta =1,+                nround =2, objective ="binary:logistic")[0]train-error:0.046522[1]train-error:0.022263

我们迭代了两次,可以看到函数输出了每一次迭代模型的误差信息。这里的数据是稀疏矩阵,当然也支持普通的稠密矩阵。如果数据文件太大不希望读进R中,我们也可以通过设置参数data = 'path_to_file'使其直接从硬盘读取数据并分析。目前支持直接从硬盘读取libsvm格式的文件。

做预测只需要一句话:

pred <- predict(bst,test$data)

做交叉验证的函数参数与训练函数基本一致,只需要在原有参数的基础上设置nfold:

> cv.res <- xgb.cv(data = train$data, label = train$label, max.depth =2, +                  eta =1, nround =2, objective ="binary:logistic", +                  nfold =5)[0]train-error:0.046522+0.001102test-error:0.046523+0.004410[1]train-error:0.022264+0.000864test-error:0.022266+0.003450> cv.res  train.error.mean train.error.std test.error.mean test.error.std1:0.0465220.0011020.0465230.0044102:0.0222640.0008640.0222660.003450

交叉验证的函数会返回一个data.table类型的结果,方便我们监控训练集和测试集上的表现,从而确定最优的迭代步数。

二、高速准确

上面的几行代码只是一个入门,使用的样例数据没法表现出xgboost高效准确的能力。xgboost通过如下的优化使得效率大幅提高:

xgboost借助OpenMP,能自动利用单机CPU的多核进行并行计算。需要注意的是,Mac上的Clang对OpenMP的支持较差,所以默认情况下只能单核运行。

xgboost自定义了一个数据矩阵类DMatrix,会在训练开始时进行一遍预处理,从而提高之后每次迭代的效率。

在尽量保证所有参数都一致的情况下,我们使用希格斯子竞赛的数据做了对照实验。

Model and Parametergbmxgboost

1 thread2 threads4 threads8 threads

Time (in secs)761.48450.22102.4144.1834.04

以上实验使用的CPU是i7-4700MQ。python的sklearn速度与gbm相仿。如果想要自己对这个结果进行测试,可以在比赛的官方网站下载数据,并参考这份demo中的代码。

除了明显的速度提升外,xgboost在比赛中的效果也非常好。在这个竞赛初期,大家惊讶地发现R和python中的gbm竟然难以突破组织者预设的benchmark。而xgboost横空出世,用不到一分钟的训练时间便打入当时的top 10,引起了大家的兴趣与关注。准确度提升的主要原因在于,xgboost的模型和传统的GBDT相比加入了对于模型复杂度的控制以及后期的剪枝处理,使得学习出来的模型更加不容易过拟合。更多算法上的细节可以参考这份陈天奇给出的介绍性讲义

三、进阶特征

除了速度快精度高,xgboost还有一些很有用的进阶特性。下面的“demo”链接对应着相应功能的简单样例代码。

只要能够求出目标函数的梯度和Hessian矩阵,用户就可以自定义训练模型时的目标函数。demo

允许用户在交叉验证时自定义误差衡量方法,例如回归中使用RMSE还是RMSLE,分类中使用AUC,分类错误率或是F1-score。甚至是在希格斯子比赛中的“奇葩”衡量标准AMSdemo

交叉验证时可以返回模型在每一折作为预测集时的预测结果,方便构建ensemble模型。demo

允许用户先迭代1000次,查看此时模型的预测效果,然后继续迭代1000次,最后模型等价于一次性迭代2000次。demo

可以知道每棵树将样本分类到哪片叶子上,facebook介绍过如何利用这个信息提高模型的表现。demo

可以计算变量重要性并画出树状图。demo

可以选择使用线性模型替代树模型,从而得到带L1+L2惩罚的线性回归或者logistic回归。demo

这些丰富的功能来源于对日常使用场景的总结,数据挖掘比赛需求以及许多用户给出的精彩建议。

四、未来计划

现在,机器学习工具在实用中会不可避免地遇到“单机性能不够”的问题。目前,xgboost的多机分布式版本正在开发当中。基础设施搭建完成之日,便是新一轮R包开始设计与升级之时。

结语

我为xgboost制作R接口的目的就是希望引进好的工具,让大家使用R的时候心情更愉悦。总结下来,xgboost的特点有三个:速度快,效果好,功能多,希望它能受到大家的喜爱,成为一驾新的马车。

xgboost功能较多,参数设置比较繁杂,希望在上手之后有更全面了解的读者可以参考项目wiki。欢迎大家多多交流,在项目issue区提出疑问与建议。我们也邀请有兴趣的读者提交代码完善功能,让xgboost成为更好用的工具。

另外,在使用github开发的过程中,我深切地感受到了协作写代码带来的变化。一群人在一起的时候,可以写出更有效率的代码,在丰富的使用场景中发现新的需求,在极端情况发现隐藏很深的bug,甚至在主代码手拖延症较为忙碌的时候有人挺身而出拿下一片issue。这样的氛围,能让一个语言社区的交流丰富起来,从而充满生命力地活跃下去。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容