集成学习-Boosting集成学习算法XGBoost
XGBoost全名叫(eXtreme Gradient Boosting)极端梯度提升,经常被用在一些项目中,其效果显著。它是大规模并行boosted tree的工具,它是目前最快最好的开源boosted tree工具包。XGBoost 所应用的算法就是GBDT(gradient boosting decision tree)的改进,既可以用于分类也可以用于回归问题中。
- 全称:eXtreme Gradient Boosting(极值梯度提升算法)
- 作者:陈天奇(华盛顿大学博士)
- 基础:GBDT
- 所属:boosting迭代型、树类算法。
- 适用范围:分类、回归等
- 优点:速度快、效果好、能处理大规模数据、支持多种语言、支持自定义损失函数等等。
目录
XGBoost和GBDT的区别
加法模型与前向分步算法
XGBoost目标损失函数推导
带正则项的Boosting Tree模型
XGBoost损失函数推导
最优切分点划分算法
XGBoost的优缺点
XGBoosting涉及的算法工程优化策略
Xgboost算法训练参数
XGBoost和GBDT的区别
XGBoost作为GBDT的高效实现,对比原算法GBDT,XGBoost主要从下面几个方面做了优化:
- XGBoost的基学习器除了可以是CART也可以是线性分类器,而GBDT只能是CART;
- XGBoost在代价函数中加入了正则项,用于控制模型的复杂度(正则项的方式不同,GBDT是一种类似于缩减系数,而XGBoost类似于L2正则化项),可以防止过拟合,泛化能力更强。
- XGBoost借鉴了随机森林的做法,支持特征抽样,不仅防止过拟合,还能减少计算;
- XGBoost工具支持并行化;
- 对于缺失值的特征,通过枚举所有缺失值在当前节点是进入左子树还是右子树来决定缺失值的处理方式。
- 在算法的优化方式上,GBDT的损失函数只对误差部分做负梯度(一阶泰勒)展开,而XGBoost损失函数对误差部分做二阶泰勒展开,更加准确。
XGBoost与深度学习对比,不同的机器学习模型适用于不同类型的任务。深度神经网络通过对时空位置建模,能够很好地捕获图像、语音、文本等高维数据。而基于树模型的XGBoost则能很好地处理表格数据,同时还拥有一些深度神经网络所没有的特性(如:模型的可解释性、输入数据的不变性、更易于调参等)。
加法模型与前向分步算法
GBDT和XGBoost的算法核心都是:先构造一个(决策)树,然后不断在已有模型和实际样本输出的残差上再构造一颗树,依次迭代。算法都使用了前向分布算法的思路,从前向后,每一步学习一个基函数及其系数,最终逐步逼近优化目标函数式。
前向分布算法的前提,还需要介绍一下加法模型:
如果给定了损失函数L,所以前向分布算法考虑的问题是,如何求出所有的βm和γm,那我们的优化目标即为:
显然一次性求出所有的βm和γm基本不可能,所以前向分布算法给出的解决办法是:“利用贪心算法,每一步只学习一个弱模型及其系数,使得当前弱模型和之前所有的弱模型组合后目标表达式取得最优值,最终就可以使得所有弱模型组合后目标表达式取得最优值”。
下面通过一个具体的例子来说明:预测一个人是否喜欢电脑游戏,下图表明小男孩更喜欢打游戏,预测的结果为 tree1 和 tree 2 累加的结果2.9。
总之,提升方法告诉我们如何来求一个效果更好模型,那就是将多个弱模型组合起来,这仅仅是一个思路,而前向分布算法就具体告诉我们应该如何来做。
XGBoost目标损失函数推导
带正则项的Boosting Tree模型
其中,γγ为L1L1正则的惩罚项,λλ为L2L2正则的惩罚项
复杂度计算例子如下:
XGBoost损失函数推导
最优切分点划分算法
在实际训练过程中,当建立第 t 棵树时,一个非常关键的问题是如何找到叶子节点的最优切分点,XGBoost支持两种分裂节点的方法——贪心算法和近似算法。
(1)贪心算法
从树的深度为0开始:
- 对每个叶节点枚举所有的可用特征;
- 针对每个特征,把属于该节点的训练样本根据该特征值进行升序排列,通过线性扫描的方式来决定该特征的最佳分裂点,并记录该特征的分裂收益;
- 选择收益最大的特征作为分裂特征,用该特征的最佳分裂点作为分裂位置,在该节点上分裂出左右两个新的叶节点,并为每个新节点关联对应的样本集;
- 回到第1步,递归执行直到满足特定条件为止;
那么如何计算每个特征的分裂收益呢?
假设我们在某一节点完成特征分裂,则分裂前的目标函数可以写为:
分裂后的目标函数为:
则对于目标函数来说,分裂后的收益为:
注意: 该特征收益也可作为特征重要性输出的重要依据。
对于每次分裂,我们都需要枚举所有特征可能的分割方案,如何高效地枚举所有的分割呢?
假设我们要枚举某个特征所有 x<a 这样条件的样本,对于某个特定的分割点 a 我们要计算 a 左边和右边的导数和。
我们可以发现对于所有的分裂点 a ,只要做一遍从左到右的扫描就可以枚举出所有分割的梯度和GL、GR 。然后用上面的公式计算每个分割方案的收益就可以了。
观察分裂后的收益,我们会发现节点划分不一定会使得结果变好,因为我们有一个引入新叶子的惩罚项,也就是说引入的分割带来的增益如果小于一个阀值的时候,我们可以剪掉这个分割。
(2)近似算法
贪心算法可以得到最优解,但当数据量太大时则无法读入内存进行计算,近似算法主要针对贪心算法这一缺点给出了近似最优解。
对于每个特征,只考察分位点可以减少计算复杂度。
该算法首先根据特征分布的分位数提出候选划分点,然后将连续型特征映射到由这些候选点划分的桶中,然后聚合统计信息找到所有区间的最佳分裂点。
在提出候选切分点时有两种策略:
Global:学习每棵树前就提出候选切分点,并在每次分裂时都采用这种分割;
Local:每次分裂前将重新提出候选切分点。直观上来看,Local策略需要更多的计算步骤,而Global策略因为节点已有划分所以需要更多的候选点。
下图给出不同种分裂策略的AUC变化曲线,横坐标为迭代次数,纵坐标为测试集AUC,eps为近似算法的精度,其倒数为桶的数量。
我们可以看到 Global 策略在候选点数多时(eps 小)可以和 Local 策略在候选点少时(eps 大)具有相似的精度。此外我们还发现,在 eps 取值合理的情况下,分位数策略可以获得与贪婪算法相同的精度。
XGBoost的优缺点
优点:
(1)并行处理,支持并行化。boosting技术中下一棵树依赖上一棵树的残差进行训练和预测,所以树与树之间应该是只能串行。但是同层级节点可并行,具体的对于某个节点,节点内选择最佳分裂点,进行枚举的时候并行,(据说恰好这个也是树形成最耗时的阶段)。候选分裂点计算增益用多线程并行,训练速度快。
(2)高度的灵活性。XGBoost 允许用户定义自定义优化目标函数和评价标准。
(3)缺失值处理。XGBoost内置处理缺失值的规则。用户需要提供一个和其它样本不同的值,然后把它作为一个参数传进去,以此来作为缺失值的取值。XGBoost在不同节点遇到缺失值时采用不同的处理方法,并且会学习未来遇到缺失值时的处理方法。
(4)内置交叉验证。XGBoost允许在每一轮boosting迭代中使用交叉验证。因此,可以方便地获得最优boosting迭代次数。而GBM使用网格搜索,只能检测有限个值。early stop,当预测结果已经很好的时候可以提前停止建树,加快训练速度。
(5)XGBoost还特别设计了针对稀疏数据的算法
假设样本的第i个特征缺失时,无法利用该特征对样本进行划分,这里的做法是将该样本默认地分到指定的子节点,至于具体地分到哪个节点还需要某算法来计算,算法的主要思想是,分别假设特征缺失的样本属于右子树和左子树,而且只在不缺失的样本上迭代,分别计算缺失样本属于右子树和左子树的增益,选择增益最大的方向为缺失数据的默认方向(论文中“枚举”指的不是枚举每个缺失样本在左边还是在右边,而是枚举缺失样本整体在左边,还是在右边两种情况。 分裂点还是只评估特征不缺失的样本。);
(6)XGBoost还提出了三种防止过拟合的方法:Shrinkage and Column Subsampling、正则化项
Shrinkage方法就是在每次迭代中对树的每个叶子结点的分数乘上一个缩减权重η,这可以使得每一棵树的影响力不会太大,留下更大的空间给后面生成的树去优化模型。Column Subsampling类似于随机森林中的选取部分特征进行建树。其可分为两种,一种是按层随机采样,在对同一层内每个结点分裂之前,先随机选择一部分特征,然后只需要遍历这部分的特征,来确定最优的分割点。另一种是随机选择特征,则建树前随机选择一部分特征然后分裂就只遍历这些特征。一般情况下前者效果更好。
缺点
(1)虽然利用预排序和近似算法可以降低寻找最佳分裂点的计算量,但是xgBoosting采用预排序,在迭代之前,对结点的特征做预排序,需要遍历数据集选择最优分割点,数据量大,非常耗时;LightGBM方法采用histogram算法,占用的内存低,数据分割的复杂度更低;
(2)预排序过程的空间复杂度过高,不仅需要存储特征值,还需要存储特征对应样本的梯度统计值的索引,相当于消耗了两倍的内存。
(3)xgBoosting采用level-wise生成决策树,同时分裂同一层的叶子,从而进行多线程优化,不容易过拟合,但很多叶子节点的分裂增益较低,没必要进行跟进一步的分裂,这就带来了不必要的开销;LightGBM采用深度优化,leaf-wise生长策略,每次从当前叶子中选择增益最大的结点进行分裂,循环迭代,但会生长出更深的决策树,产生过拟合,因此引入了一个阈值进行限制,防止过拟合。
XGBoosting涉及的算法工程优化策略
(1) 对内存的优化(列分块)
在XGBoost模型计算过程中,特征值的排序与切分点的选择是最耗时的部分,文章中提出了一种划分块的优化方法,具体表现为如下流程:
- 整体训练数据可以看做一个n*m 的超大规模稀疏矩阵
- 按照mini-batch的方式横向分割,可以切成很多个“Block”
- 每一个“Block”内部采用一种Compress Sparse Column的稀疏短阵格式,每一列特征分别做好升序排列,便于搜索切分点,整体的时间复杂度有效降低。
(2)对CPU Cache的优化
针对一个具体的块(block),其中存储了排序好的特征值,以及指向特征值所属样本的索引指针,算法需要间接地利用索引指针来获得样本的梯度值。由于块中数据是按特征值来排序的,当索引指针指向内存中不连续的样本时,无法充分利用CPU缓存来提速。文章中作者提出来了两种优化思路。
- 提前取数(Prefetching)
对于精确搜索,利用多线程的方式,给每个线程划分一个连续的缓存空间,当training线程在按特征值的顺序计算梯度的累加时,prefetching线程可以提前将接下来的一批特征值对应的梯度加载到CPU缓存中。
- 合理设置分块大小
对于近似分桶搜索,按行分块时需要准确地选择块的大小。块太小会导致每个线程的工作量太少,切换线程的成本过高,不利于并行计算;块太大导致缓存命中率低,需要花费更多时间在读取数据上。经过反复实验,作者找到一个合理的block_size
。
(3)对IO的优化
当数据集太大,无法全部加载到内存时,主要的性能瓶颈就变成了磁盘IO,因此需要对IO进行优化。文章中主要提出来了两种优化思路。
- Block压缩优化
原始数据在磁盘上是以压缩格式存取的,读取的时候,现场解压 (decompress on-the-fly)
相当于牺牲一部分CPU时间,换取对磁盘IO的读取时间损耗。
- Block 分片优化
将压缩后的块存放在多个不同的磁盘中,每个磁盘开一个prefetching线程分别读取数据到各自的缓存,提供给一个training线程使用。
Xgboost算法训练参数
XGBoost可以把所有的参数分成了三类:
- 通用参数:宏观函数控制。
- Booster参数:控制每一步的booster(tree/regression)。
- 学习目标参数:控制训练目标的表现。
(1)通用参数
这些参数用来控制XGBoost的宏观功能。
booster[默认gbtree]
- 选择每次迭代的模型,有两种选择:
gbtree:基于树的模型
gbliner:线性模型
silent[默认0]
- 当这个参数值为1时,静默模式开启,不会输出任何信息。
- 一般这个参数就保持默认的0,因为这样能帮我们更好地理解模型。
nthread[默认值为最大可能的线程数]
- 这个参数用来进行多线程控制,应当输入系统的核数。
- 如果你希望使用CPU全部的核,那就不要输入这个参数,算法会自动检测它。
还有两个参数,XGBoost会自动设置,目前你不用管它。接下来咱们一起看booster参数。
尽管有两种booster可供选择,我这里只介绍tree booster,因为它的表现远远胜过linear booster,所以linear booster很少用到。
- 决定最小叶子节点样本权重和。
- 和GBM的 min_child_leaf 参数类似,但不完全一样。XGBoost的这个参数是最小样本权重的和,而GBM参数是最小样本总数。
- 这个参数用于避免过拟合。当它的值较大时,可以避免模型学习到局部的特殊样本。
- 但是如果这个值过高,会导致欠拟合。这个参数需要使用CV来调整。
- 这参数限制每棵树权重改变的最大步长。如果这个参数的值为0,那就意味着没有约束。如果它被赋予了某个正值,那么它会让这个算法更加保守。
- 通常,这个参数不需要设置。但是当各类别的样本十分不平衡时,它对逻辑回归是很有帮助的。
- 这个参数一般用不到,但是你可以挖掘出来它更多的用处。
- 和GBM中的subsample参数一模一样。这个参数控制对于每棵树,随机采样的比例。
- 减小这个参数的值,算法会更加保守,避免过拟合。但是,如果这个值设置得过小,它可能会导致欠拟合。
- 典型值:0.5-1
- 用来控制树的每一级的每一次分裂,对列数的采样的占比。
- 我个人一般不太用这个参数,因为subsample参数和colsample_bytree参数可以起到相同的作用。但是如果感兴趣,可以挖掘这个参数更多的用处。
- 权重的L2正则化项。(和Ridge regression类似)。
- 这个参数是用来控制XGBoost的正则化部分的。虽然大部分数据科学家很少用到这个参数,但是这个参数在减少过拟合上还是可以挖掘出更多用处的。
- 这个参数定义需要被最小化的损失函数。最常用的值有:
- binary:logistic 二分类的逻辑回归,返回预测的概率(不是类别)。
- multi:softmax 使用softmax的多分类器,返回预测的类别(不是概率)。 在这种情况下,你还需要多设一个参数:num_class(类别数目)。
- multi:softprob 和multi:softmax参数一样,但是返回的是每个数据属于各个类别的概率。
2、eval_metric[默认值取决于objective参数的取值]
- 对于有效数据的度量方法。
- 对于回归问题,默认值是rmse,对于分类问题,默认值是error。
- 典型值有:
- rmse 均方根误差(∑Ni=1ϵ2N−−−−−√∑i=1Nϵ2N)
- mae 平均绝对误差(∑Ni=1|ϵ|N∑i=1N|ϵ|N)
- logloss 负对数似然函数值
- error 二分类错误率(阈值为0.5)
- merror 多分类错误率
- mlogloss 多分类logloss损失函数
- auc 曲线下面积
集成学习-Boosting集成学习算法XGBoost相关推荐
- 集成学习-Boosting集成学习算法GBDT
GBDT算法的核心为:先构造一个(决策)树,然后不断在已有模型和实际样本输出的残差上再构造一颗树,依次迭代. 目录 Decistion Tree(决策树) Gradient Boosting(梯度提升 ...
- 集成学习-Boosting集成学习算法LightGBM
在2017年年1月微软在GitHub的上开源了一个新的升压工具LightGBM(Light Gradient Boosting Machine ).它是一种优秀的机器学习算法框架,与XGBoost算法 ...
- 集成学习-Boosting集成学习算法AdaBoost
Boosting是一族将弱学习器提升为强学习器的算法,适用于个体学习器间存在强依赖关系.必须串行生成序列化方法.最著名的代表是AdaBoost. Boosting的工作机制:从初始的训练集中训练出一个 ...
- 机器学习集成模型学习——Boosting集成学习(四)
Boosting Boosting模型是线性训练的,后面的模型会纠结于前一个模型预测错的部分,然后尝试把它修正,步骤如下: 第一个模型用一部分训练集训练,得出这部分训练集上的错误点 错误的数据会有更大 ...
- 深入理解提升树(Boosting tree)算法
我的个人微信公众号:Microstrong 微信公众号ID:MicrostrongAI 微信公众号介绍: Microstrong(小强)同学主要研究机器学习.深度学习.计算机视觉.智能对话系统相关内容 ...
- 机器学习笔记(六)Boosting集成学习算法Adaboost和GBDT
一.前言 在前一篇文章中我们介绍了集成学习算法中的Bagging模型,本篇文章将继续介绍集成学习算法中的另一个代表性算法Boosting模型.Boosting是一种可将弱学习器提升为强学习器的算法,其 ...
- 集成学习boosting算法:AdaboostGBDTXgboostLightGBMCatBoost
Adaboost&GBDT&Xgboost&LightGBM&CatBoost 0简介 0.0发展史 0.1 经典文章链接/文章总结链接 0.2 bagging和boo ...
- 04 集成学习 - Boosting - AdaBoost算法构建
03 集成学习 - Boosting - AdaBoost算法原理 十.AdaBoost算法构建 上一章最后说明了每个基模型的权值α是如何求得的,于是我就可以对模型进行更新操作了. 构建过程一 1.假 ...
- 笔记—集成学习—Boosting
集成学习--Boosting 一.引言 在机器学习的有监督学习算法中,我们的目标是学习出一个稳定的且在各个方面表现都较好的模型.但是,实际情况往往不这么理想,有时我们只能得到多个有偏好的模型(弱监督模 ...
最新文章
- python ggplot为什么不能取代matplotlib_Matplotlib vs ggplot2
- Docker Overlay 介绍
- inline函数学习笔记
- YY一下,扎克伯格做了一个什么样的AI家居助手?
- js获取字符串的字节数
- vue项目实现详情页后退缓存之前的数据
- OpenCV2:Mat属性type,depth,step
- linux 内核编程视频
- 互联网晚报 |10/12 |中国汽车出口量跃居全球第二;统一充电接口或让苹果每年损失百亿;《财富》杂志公布“改变世界的公司”榜单...
- 计算机提示无法识别优盘,U盘插入电脑提示无法识别的解决方法
- untiy 串口通信
- SQLI DUMB SERIES-2
- J9数字论:DAO与Web3的联系
- 浏览器Cookie的设置与获取
- 如何通过python获取股票行情信息?
- 完美解决TP-LINK无线路由桥接后电脑能上网、手机不能上的问题
- R语言——水仙花数(向量化运算)
- 高通平台5G注册问题分析
- 软件工程——三次软件危机的表现及起因
- python程序停止运行语句_怎么停止python脚本
热门文章
- XtraReport交叉表自适应行高及最佳列宽(转)
- SpringBoot项目依赖本地jar包
- Error:org.gradle.api.internal.changedetection.state.FileCollectionSnapshotImpl cannot be cast to org
- 干 MySQL 两千万数据的大表优化解决过程,三种厉害的解决方案
- 赞!这样构建微服务架构,实在是太轻松了!
- 代码对比工具,我就用这 6 个!
- 用 Spring Boot 纯手工打造私人云网盘!!!
- 不止 JDK7 的 HashMap ,JDK8 的 ConcurrentHashMap 也会造成 CPU 100%?原因与解决~
- 图解从 URL 到网页通信原理
- 不改表结构如何动态扩展字段