公司在招聘面试候选人时,面试的人一般是HR、小组主管和部门经理,过程可以分为两种形式。 第一种形式是三位面试官分别单独面试候选人,问的问题可能相同也可能不同,面试官会根据候选人的表现分别给出结论,最后综合三位的结论来决定录用与否。这就是Bagging。Bagging由Bootstrap AGGragatING缩写而来,是并行式集成学习方法的著名代表。它基于自助抽样法(bootstrap sampling)来获得多个采样集,每个采样集独立地训练出一个基学习器,然后对所有基学习器的预测结果进行投票或者平均来获得最终的结果。Bagging的典型代表是Random Forests。第二种形式是群面。HR、小组主管和部门经理同时参加了面试,HR先问了几个问题,小组主管根据候选人对HR的回应问了另外一些问题,最后部门经理在小组主管问题的基础上问了其他一些问题。最后综合三位面试官对候选人的打分决定录取或不录取。这就是Boosting。Boosting是一种可将弱学习器提升为强学习器的串行集成学习算法。“[周志华,机器学习]:先从初始训练集训练出一个基学习器,再根据基学习器的表现对训练样本分布进行调整,使得先前基学习器做错的训练样本在后续受到更多关注,然后基于调整后的样本分布来训练下一个基学习器。如此重复进行,直至基学习器数目达到事先指定的值,最终将这些基学习器进行加权结合”。Boosting的典型代表有AdaBoost和GBDT系列(XGBoost、LightGBM、CatBoost)。GBDT即梯度提升决策树(Gradient Boosting Decision Tree),GBDT也叫MART(Multiple Additive Regression Tree),如果是回归任务则被称为梯度提升回归树(Gradient Boosting Regression Tree)。不同的Boosting算法调整分布的方法是不同的,比如AdaBoost算法,在每一轮迭代中都会更新样本的权重,将学错样本的权重调高,而在GBDT中则是更新回归目标,将新一轮迭代模型的损失函数的负梯度作为新一轮的标签训练出一个新的弱分类器,最终实现模型的更新。当损失函数为平方损失函数的时候,当前模型损失函数的负梯度值刚好等于残差,此时每一轮建立的新的基学习器都在减少残差。梯度是一种数学概念(一个矢量,其方向上的方向导数最大,其大小正好是此最大方向导数),一个函数的梯度方向是函数上升最快的方向,负梯度方向是函数下降最快的方向。与并行的Bagging的不同在于,Boosting是一个接一个的来训练基学习器(串行),每一个基学习器都是在修正前面学习器偏差的基础上给出决策,后一个模型参数设置需要前一轮模型预测结果。Bagging采用的是有回放的Bootstrap自主抽样来从原始数据集中选出每一轮迭代的训练集,不同的训练集之间是相对独立的,而Boosting每一轮的训练集并没有发生变化,只是训练集中每个个案在不同的基学习器中的权重在更新。Bagging的训练集中,每个样本的权重是相同的,每个基学习器在最终决策中权重也是一样的,但Boosting的训练集中每个样本的权重不同(偏差越大权重越大),而且可以让每个基学习器在最终决策中权重也不一样(分类误差越小权重越大)。XGBoost模型(XGBoost:eXtreme Gradient Boosting)是基于boosting框架的一种提升树模型。直接跳过GBDT来理解XGBoost确实不是一件容易的事情,此次笔记通过释义xgboost::xgb.train函数的各种参数来理解XGBoost模型的算法。其后用一个示例来实操演示一下过程。xgboost::xgb.train提供了三种基学习器:树提升器、线性提升器和基于深度神经网络的dropout 技术的提升树模型。其中树模型是最为常用的基学习器。节、节点(Node):树模型中满足某个标准的一个个案的群体; 分枝(Split):种树时依据某种原则选择分类属性和拆分点将样本分为不同亚群; 边(Edge):父结点指向子结点的连线; 根节点(Root Node):树的起始点(包括所有个案),根节点没有父节点; 叶节点(Leaf Node):树的终止节点,叶节点没有子节点; 节点的度(Degree):结点的子结点个数,二叉树的度最大为2; 节点的层(Level):根结点的层为1 ,根结点的子结点的层为 2,……; 节点的高度(Height):离该结点最远的叶结点到该结点所经过的边的数量; 节点的深度(Depth):根结点到该结点所经过的边的数量; 树的深度(Depth):等于树的高度,根结点到离根结点最远的叶结点所经过的边的数量。 在传统的医学统计中,样本(Samp1e)指的是从总体(Population)中随机抽取的部分观察单位(Observed unit),这里的观察单位是统计研究的基本单位,即个体/个案(Individual,Case)。但在机器学习领域,样本(Samp1e)或示例 (Instance)描述的却是个体。另外传统医学统计中的自变量(Independent variable ,也称解释变量、预测变量)在机器学习领域称为属性(Attribute)或特征(Feature),而传统医学统计中的因变量(Dependent variable,应变量、被解释变量、响应/反应变量、结局变量)在机器学习领域则称为标签(label)。 XGBoost模型理论介绍及介绍PPT(来自xgboost算法的发明者陈天奇):Tianqi Chen,Carlos Guestrin.XGBoost: A Scalable Tree Boosting.System. https://github.com/dmlc/xgboost. Tianqi Chen.Introduction to Boosted Trees. Tianqi Chen’s PPT2014 from http://www./ 如网络受限,可从留言中提供的地址下载。 eXtreme Gradient Boosting Training函数(xgboost包):xgb.train(params=list(),data,nrounds,watchlist=list(),obj=NULL,feval=NULL,verbose=1,print_every_n=1L,early_stopping_rounds=NULL,maximize=NULL,save_period=NULL,save_name="xgboost.model",xgb_model=NULL,callbacks=list(),...) xgboost(data=NULL,label=NULL,missing=NA,weight=NULL,params=list(),nrounds,verbose=1,print_every_n=1L,early_stopping_rounds=NULL,maximize=NULL,save_period=NULL,save_name="xgboost.model",xgb_model=NULL,callbacks=list(),...)注:参数中的下划线“_”也可以使用点“.”来替换。xgb.train是一个用于训练XGBoost模型的高级函数,xgboost函数则是xgb.train的一个更简单的包装器。 函数的各项参数释义: params:参数列表。主要包括三类:通用参数(General Parameters)、提升器参数(Booster Parameters)和任务参数(Task Parameters)。通用参数主要选择基学习器类型,如树模型还是线性模型;提升器参数针对选择的基学习器进行的设置;学习任务参数主要是指定训练模型的损失函数,使用验证集做模型评估时指定评价指标等。参数详情介绍可参考xgboost包帮助文件和XGBoost文件[https://xgboost./en/latest/parameter.html]。 [1]通用参数 [2]提升器参数 注:XGBoost集成模型由K个可加性函数组成。上述表达式中的y^i表示的是整个集成模型对某个个案i的估计值。这里的可加函数就是基学习器,XGBoost的基学习器常用树模型,也可以是线性模型。当采用树模型时,XGBoost是基于回归树的集成算法,单棵树是回归树而不是分类树。回归树跟决策树具有相同的决策规则,不同的是回归树的每个叶节点输出是一个分值(Score),而不是一个标签(label,结局)。从这个角度理解,回归树就是一个将属性映射到叶节点Score值的函数,其参数有两部分,一部分是叶节点索引函数q(结构部分),其作用是将属性映射到具体的某个叶节点上,即预测结果应该属于哪一个叶节点;第二部分是该叶节点的输出权重值w(权重部分),即前面说的Socre值,输出权重值是一个长度为T的的一维向量(T是树叶节点的的数目)。回归树通过这个预测分值实现回归、分类、排序等目的,实现什么样的目的取决于如何定义目标函数。Additive Training (Boosting) : 注:y^(t)i表示第t轮迭代后的集成模型对个体i的估计值,并不是第t树单独的预测结果。一个由K棵树组成的XGBoost集成模型,经过了K轮提升迭代。每次迭代过程中都会新生成一棵树加入到当前模型中,更新已有的模型(即所谓的Additive training或者叫Boosting)。经过t轮迭代的模型(当前模型)预测结果=前面经过t-1轮迭代的模型预测结果+第t棵提升树的输出结果。“前面经过t-1轮迭代的模型”是已经优化好的确定模型,“第t棵提升树的输出结果”是第t棵树的叶节点输出值。每轮迭代的结果是对集成模型的一次提升,第t颗树只是当前模型的一个“子模型”,其构造就是为了减少前t-1轮迭代后仍可能存在的误差。每棵树(每个函数)贡献的只是一个增量,最终模型等于每次迭代增量的累加和。目标函数与模型复杂度: 注:XGBoost的目标函数也就是整个模型的损失函数,由两部分组成:第一部分是传统损失函数,即训练误差,衡量模型对数据的拟合程度,鼓励低偏差(Bias);第二部分是正则化项,惩罚复杂的模型鼓励简单的模型,降低方差(Variance),从而控制模型的复杂程度防止过拟合。每一轮迭代的任务就是寻找一个使目标函数降低最大的函数ft(xi)[注:函数ft(xi)就是第t棵提升树]。由于在构造第t颗树的时候,前t-1轮迭代的模型都已经是确定好的,不管它们的复杂度是多少都已经是一个常数了,所以上述公式中的常数项(constant)是前面经过t-1轮迭代的集成模型的复杂度(或者说t-1颗树的复杂度的累加和)。公式经泰勒二阶展开并进行一些列的变简化(模型的尽头是数学@_@,这里面的数学已经超出了笔者能讲明白的理解范围了),结果如下:其中gi和hi分别为损失函数在yi(t-1)处的梯度(损失函数的一阶导数)和Hessian矩阵(损失函数的二阶导数)。梯度是一种数学概念(一个矢量,其方向上的方向导数最大,其大小正好是此最大方向导数),一个函数的梯度方向是函数上升最快的方向,负梯度方向是函数下降最快的方。树的复杂度定义:γ*叶节点数+1/2*α*L1范数+1/2*λ*L2范数2 叶节点数量越多,意味着树的分裂次数越多,树的深度越大,树越复杂。树的复杂度可以用树的深度、内部节点个数、叶子节点个数(T)、叶节点输出分值(W)等来衡量。在基学习器是CART决策树时,XGBoost复杂度可以分拆成叶节点的个数T和叶节点的输出权重值w两部分。其中叶节点数量被赋予了一个权重γ(这个权重实际上是节点的拆分点的拆分阈值,见后面介绍),而叶节点的权重值则是进行了正则化。以仅对权重进行L2正则化为例,复杂度可以简化为: 结合前面对回归树的函数定义,目标函数可以演化成(权重L2正则化): 在树结构q(x)确定后, 这一轮的目标函数其实就可以确定了下来。因为据此可以获得使前这一轮(第t轮)目标函数最小的叶结点j的最优权重值w*,以及目标函数的最小值(最优值): 其实这就是一个一元二次方程,求w等于多少时Obj最小,最小值是多少。最优权重值w*可通过损失函数的梯度和Hessian矩阵获得。目标函数的最优值也被称为结构分数(structure score),表示在指定一个树的结构的时,当前这一轮的目标函数最多减少值。其值越小,结构越好。神奇之处在于最优目标函数(结构分数)竟然与权重没有一毛钱的关系。那如何确定树的结构呢?这就是: 树的生长与剪枝: 树的生长最主要就是确定最佳的分裂属性和拆分点,理论上这需要枚举所有特性上的所有可能的拆分点(精确贪婪算法),想想这种计算量都恐怖,所以还会常用一些其他的近似算法,比如先将数据分箱。分类变量建议先进行独热编码(one-hot encoding)进行编码。 分裂后的增益Gain=分裂后-分裂前的结构分数,分裂后的结构分数等于左子树的结构分数和右子树的结构分数之和。Gain值越大,说明分裂后能使目标函数减少越多,就越好: 新的分裂不一定会使得情况变得更好,为优化这个目标(对树进行剪枝),引入了新叶子的惩罚项γ。新的分裂是否合理可以看这个分裂能否降低足够多的损失函数(结构分数)。“足够多”是多少呢?这就是γ,你可以把它理解为叶节点是否应该进一步拆分的阈值,当新的分裂带来的损失函数的减少(增益)小于这个γ值的时候就不进行分裂操作。在树的复杂度定义里,它是叶节点数量的一个权重(见前面复杂度定义),经过数学上的变换,它被赋予了新的含义:拆分阈值。最佳的γ值也就是使损失函数减少最大时的最佳分割。提升树算法要点: 公式中的ε(上图中使用了ε的变体)是迭代提升的步长(step-size)或收缩率(shrinkage),相当于GBDT中的学习率。在R的xgboost函数中由参数eta来指定,通常设置为0.1左右,在R中则是默认0.3。这是一个收缩参数,可以理解为当前树(第t棵树)叶节点输出值的贡献率,收缩率的加入减少了每提升棵树的影响,为后面的树留下了更多的预测空间,使得提升过程更加保守稳健从而能防止模型过拟合。η值越小意味着模型需要更多的迭代次数,但需要计算量越大收敛越慢。通俗一些讲,为了避免步子过大扯着蛋(每次迈一大步很快逼近结果的方式容易过拟合),每次只迈一小步(也就是每轮的迭代中给每棵树的输出结果上乘上一个收缩率η),因为每棵树的结果都不值得你掏心掏肺的完全信任,他们只能代表真理的一部分,不过我们可以多学几棵来弥补这种不足。2.2 gblinear参数 - lambda:L2正则化的加权参数,默认值为0,值越大模型越保守;
alpha:L1正则化的加权参数,默认值为0,值越大模型越保守; updater:拟合线性模型的算法。默认是shotgun,基于shotgun算法的平行坐标下降算法;coord_descent表示采用普通坐标下降算法 feature_selector:特征选择和排序方法。可选项有cyclic,shuffle,random,greedy,thrifty; top_k:当feature_selector设置为greedy和thrifty时,最多选用的特征数量,默认0表示选用所有的特征。
2.3 dart参数 DART(Dropouts Multiple Additive Regression Trees,Dropout加性回归树模型)。 XGBoost结合了大量的回归树和较小的学习率,这种情况下,相比后期添加的树,早期添加的树更为重要。为解决过拟合问题,使得最终的集成模型中各个树的贡献更加平均一些,DART构建新树时删除了一些不重要的普通树。DART利用了深度神经网络中Dropout(随机失活正则化)技巧,当计算下一棵树要拟合的负梯度时,只考虑现有集成树的一个随机子集(when computing the gradient that the next tree will fit, only a random subset of the existing ensemble is considered),或者说从现有的集成树中随机丢弃一部分树,仅用剩余的一部分树来计算下一棵树的标签(负梯度)。当将新树添加到集成模型中时,模型结果会超调,因此DART还要执行一个归一化步骤。 新构建的树以及丢弃的树都是为了减小当前模型与最佳预测器之间的差距。这里其实不太容易理解。Dropout这个动作每次迭代都会重新进行一次,这一轮迭代中没有使用的树在下一次迭代中可能又会被选中,当然也可能不会被选中。每一轮迭代中为计算下一棵树的标签而随机丢弃的树跟新生成的树一样,其生成都是采用Dropout技术来生成的,也都将是最终集成模型的一部分。经过m轮的迭代,集成模型对个体i进行预测时,仍然要使用m棵树来进行,包括构建第m棵树时随机选择的树、随机丢弃的树和第m棵树。 采用了Dropout技术的Boosting模型,假设第m轮训练中有K棵树被丢弃,则第m棵树要拟合的标签仅利用了m-1-K棵树(而不是m-1)来获得的,即第m颗树的构造减少的是m-1-K棵树的集成模型预测仍可能存在的误差。很显然,相比m-1棵树的模型(普通的Boosting模型),m-1-K棵树的模型对结局的解释更小一些,所以第m棵树的标签值更大一些。作为可加性模型,经过m轮迭代的集成模型有m棵树,包括被丢弃的K棵树、被选中用于计算第m树标签的m-1-K棵树以及第m棵树,这个包含了m棵树的集成模型对结果的预测很明显是偏大的,这可能就是文献上说的同时引入新树和丢弃的树会导致模型结果的超调(introducing both the new tree and the dropped trees will result in the model overshooting the target),所以when adding the new tree to the ensemble where DART performs a normalization step。怎么归一化呢?其实就是引入收缩因子,这就称作为归一化: 上述模型释义:假设第m轮训练中,有K棵树被丢弃,表示随机选择的用来估计第m棵树标签的那些树的集成模型的预测结果,表示被丢弃树的集成模型的预测结果(被丢弃树的叶节点输出值的加和),表示新树的叶节点输出值,η是学习率(见gbtree参数),b为新树与丢弃树的权重之比,α为修正因子。 目标函数如下: DART也可以看做是一种正则化,它是通过丢弃树的数量来控制正则化的大小。特别情况下,如果不丢弃树则DART和XGBoost没有什么不同,如果丢弃所有的树,DART与随机森林就没有区别了。 [3]任务参数 - objective:指定学习任务和相应的目标函数[注:此处的目标函数显然指定的是目标函数中的传统损失函数部分],格式是学习任务:目标函数,学习任务主要有回归、分类、排序和生存分析,每类学习任务可能会有不同的算法,每种算法对应的目标函数又不相同。比如reg:squarederror表示执行回归任务,使用平方损失作为损失函数;而binary:logistic表示执行二分类任务,加法模型的输出的是概率(通过sigmoid函数转换而来), 然后使用交叉熵作为损失函数,但默认的验证集评价指标是负对数似然。其他众多的内置学习任务:目标函数可参见xgboost包帮助文件和XGBoost文件。除了这些内置的目标函数,也可以将通过参数obj将自定义的函数传递给该参数;
base_score:所有个案的初始预测得分,用于设定一个初始的、全局偏差,默认值0.5; eval_metric:验证数据的评估指标,可以使用多个指标[注:帮助文件上的解释是“evaluation metrics for validation data”,这里的验证数据指的是用于评估模型性能的数据集,数据集由watchlist指定。这个指标不会影响到模型的训练,它只是模型训练完成之后用来评估模型效果的一个指标]。默认值会根据目标函数会自动分配(如回归默认rmse,分类默认logloss,排序默认平均精度均值(mAP)),也可以通过参数feval自定义一个函数传递给它。众多评估指标可参见xgboost包帮助文件和XGBoost文件; seed:随机种子。R中如果不设置并不是默认为0,而是通过R自己的RNG engine来获取; seed_per_iteration:通过迭代器编号确定种子PRNG。默认为false。 data:训练集。xgb.train需要是xgb.DMatrix对象。xgboost可以是xgb.DMatrix对象,也可以是matrix, dgCMatrix或本地数据文件;nrounds:提升轮次(迭代次数)的最大次数,也就是训练期间生成基学习器的数量;watchlist:用于评估模型性能的DMatrix数据集列表。模型在每一次迭代都会计算这些数据集的评估指标,评估指标由参数eval_metric或feval来指定。该部分的输出储存在结果对象中的evaluation_log字段中。[注:watchlist是xgb.train函数的参数,在xgboost函数中也设置此参数结果会报错(Error in check.custom.obj() : Setting objectives in 'params' and 'obj' at the same time is not allowed)];verbose:显示模型性能的一些信息,0不显示,1显示模型性能信息,2额外一些信息;print_every_n:verbose>0时,每n次迭代打印1次模型迭代过程的性能信息。默认值为1表示打印所有消息;early_stopping_rounds:指定模型性能无改善的迭代次数,达到这个标准则模型将停止训练;如设置为NULL则不触发早期停止功能;maximize:性能度量的值是否越大越好[注:有些评估指标值越小模型性能越好,比如均方误差;而有些则越大越好比如AUC]。设置为TURE则表示该值(验证得分)越大模型性能越好。如果设置了feval和early_stopping_rounds,则该参数必须设置;save_period:每几次迭代就自动保存1次模型,0表示最后保存;save_name:周期性自动保存的模型文件名称或路径;xgb_model:先前建立的用来继续训练的模型。xgb.Booster对象或者其原始数据,或先前保存的模型名称;callbacks:在提升过程中执行各种任务的回调函数列表。有些回调函数是根据参数值自动创建的,用户也可以提供现有的或他们自己的回调方法以定制训练过程;label:指定结局变量。数据是本地文件或xgb.DMatrix对象时无需提供;missing:缺失值的指示符,默认NA,有时会用0或者极值来表示。该参数仅用于稠密矩阵算法;分类变量的参数max_cat_to_onehot(是都对小于指定阈值的变量采用独热编码)和max_cat_threshold(每次拆分考虑的最大类别数)目前支持Python。@_@
|