建站论坛系统,网站权重怎么刷,好姑娘免费高清视频,wordpress环境需求本文专辑 : 茶桁的AI秘籍 - BI篇
原文链接: https://mp.weixin.qq.com/s/kLEg_VcxAACy8dH35kK3zg 文章目录 集成学习XGBoost Hi#xff0c;你好。我是茶桁。 学习总是一个循序渐进的过程#xff0c;之前两节课的内容中#xff0c;咱们去了解了LR和SVM在实际项目中是如何使…
本文专辑 : 茶桁的AI秘籍 - BI篇
原文链接: https://mp.weixin.qq.com/s/kLEg_VcxAACy8dH35kK3zg 文章目录 集成学习XGBoost Hi你好。我是茶桁。 学习总是一个循序渐进的过程之前两节课的内容中咱们去了解了LR和SVM在实际项目中是如何使用的我给大家看了两个项目都是跟分类相关一个是员工离职预测一个是男女声音识别。
其实也能看到男女声音识别也不一定都要用神经网络能找到一些关键特征把它转化为结构化的数据你也可以用机器学习来完成预测而且机器学习的效果还是非常好基本上都有百分之9798的准确性。
那今天这节课主要给大家讲解的是「机器学习的神器」也是今天最主要的内容。
这个内容希望大家多去仔细阅读如果你遇到哪些问题可以给我留言文章下或者私信都可以基本上一些容易解答的问题我都会给予回复大家保持一个良好的学习的方法。
集成学习
这些机器学习的神器都跟集成学习相关先给大家看一个概念叫集成学习。集成学习就是把多个分类器合到一起可以把它理解成叫三个臭裨将顶个诸葛亮。 集中学习里面有些策略Bagging是一种它像一个袋子一样数据是放到袋子里面去叫有放回的抽样方式。这个袋子里面如果你要做一个分类的模型会按照少数服从多数。最简单的就是一个陪审团看一看大家投票的情况这是分类问题。回归问题我们要用的是大家的平均值你预测一下薪酬他预测一下薪酬把大家预测结果相加以后除上个数就是求平均值。这些都是一个banging的策略集中学习把这些大家的结果给合并到一起。
Stacking叫做堆什么叫Stacking上图中下面的部分就是Stacking我们把它分成两类分类器分类器1也就是前面的Classifier做了特征的提取分类器2,Meta Classifier做了分类的过程。它是属于先后两阶段先做第一种再做第二种这是有先后逻辑顺序关系。如果是Bagging是没有先后逻辑关系。它是一个并行方法。你做你的我做我的最后我们可以综合起来这个结果没有先后逻辑关系。而Stacking的话是有一个先后逻辑关系的这是集成学习的不同种的学习的方式。
还有一种学习方式的话叫BoostingBoosting中文可以把它称为叫提升它也有先后的顺序。 我们看这张图原始的数据给了模型第一个分类器模型做了以后得到一些新的一些数据再喂给第二个模型然后再生成一些数据再喂给第三个模型这三个模型之间是有顺序的。先计算第一个再计算后面的第二个再计算第三个所以这种Boosting的方法是有一些顺序的关系。
通过Boosting的方式可以把弱分类器结合到一起形成一个强的分类器这是它的一个Boosting的关系。Boosting有两个比较重要的算法一个AdaBoost自适应提升 一个是Gradient Boosting梯度提升。这两种方法在咱们之前的机器学习课程中都有详细的讲解。
AdaBoost是使用前面的学习器用简单的模型去适配数据然后分析错误。然后会给予错误预测的数据更高权重然后用后面的学习器去修复。
所以集成学习是有三种模式Bagging是一种Stacking是一种还有就是Boosting。总的来说都是把多个分类器组合起来会胜过一个分类器。这几中模型之间比较常见的模型是Boosting和Bagging。 我们对这两个做个对比。
在结构上Bagging是基分类器并行处理而Boosting是串行处理。训练集上Bagging的基分类器训练是独立的而Boosting的训练集是依赖于之前的模型在作用上Bagging的作用是减少variance 而Boosting在于减少bias。
并行的方式和串形的方法没有什么特别的好坏之分如果要去判断也是跟数据相关。我今天讲解的神器是属于最后一种就是Boosting的方式所以它应该是一个串形的方法。
这种分类器里面有很多种上面我介绍了两个算法一个是AdaBoost一个是Gradient Boosting那我们主要看看后面这种算法。这个算法中包含了几个比较重要的工具有XGBoost、LightGBM、CatBoost以及NGBoost实际上是对GBDT方法的不同实现针对同一目标做了不同的优化处理。基本上出现的年限如下 Boosting这种方式典型代表是XGBoost、LightGBM和CatBoostNGBoost采用的boosting的方法跟前三种boosting不太一样通常我们机器学习的神器还是指的前面三种。当然近些年还有一些新的工具比如H2O GBM以及TensorFlow Boosted TreesTFBT咱们我们不去探讨它们以后有机会写进阶课程的时候再说。
XGBoost最早提出来的是2014年它是由陈天奇提出来的提出来以后在Kaggle的比赛中是大火基本上在2014年那个阶段只要你参加机器学习的比赛必用XGBoost而且第一名基本上都是XGBoost效果是最好的。
三年之后在2017年微软提出来了一个lightGBM的版本它是站在原来的XGBoost基础上做了一些简化让它的版本更轻轻的一个优势就是快。所以LightGBM占用内存更少速度更快。
三个月之后俄罗斯的一家公司叫Yandex又做了一个新的版本叫CatBoost这家公司你可以把它理解成是俄罗斯的Google是个科技巨头也做测速引擎同时也开源很多的机器学习的工具箱那我们现在用的CatBoost就是Yandex提出来的一个模型。
XGBoost
https://arxiv.org/abs/1603.02754 XGBoost是2014年提出来的模型它本身是基于树的。一般来说用的是CART回归树。这个是一个决策树这是它的机器学习的模型。
我们现在要去完成一个预测y值一个人是否喜欢电子游戏。就是电子游戏的市场跟哪些特征相关年龄、性别、职业这些特征。前面是我们的X有很多X最后是那个y。
现在如果要建一棵树用一棵角色树可能会建出来如图的一个过程。先判断他的age是不是小于15岁如果小于15岁就走左边再判断他的性别是不是男性如果是男性我们就认为他会玩两个小时如果不是男性就是0.1个小时。如果他是大于15岁我们就认为他是-1。
这个是其中一棵树的一个结果他的预测是在叶子节点里面会有一个数值这等于他的输出所以输出都是在叶子节点里中间那颗分支都是按照不同的逻辑来做个判断。
XGBoost它本身是集中学习其实它背后的那个过程原理叫GBDT大家先知道就好了我们今天没有详细展开GBDT这个是属于它的理论。就是说我有多少棵树一起来学习。就是之前看到那张图上的模型依照数据流Model1先去做做完以后Model2去做再做完以后Model3去做。它本身的原理就是多棵树相加。
那GBDT的理论版本是这样XGBoost是它的工程版本。工程版本的目的是要更加的泛化所以它主要是在原来GBDT的基础上又加了一个叫做正则化项 目标函数 损失函数 正则化项 O b j ( Θ ) L ( Θ ) Ω ( Θ ) \begin{align*} 目标函数 损失函数 正则化项 \\ Obj(\varTheta) L(\varTheta) \Omega(\varTheta) \end{align*} 目标函数损失函数正则化项Obj(Θ)L(Θ)Ω(Θ)
这里 L ( Θ ) L(\varTheta) L(Θ)是损失函数拟合数据。 Ω ( Θ ) \Omega(\varTheta) Ω(Θ)是正则化项惩罚复杂模型。
我们的目标函数是由损失函数加正则化项。一般我们要判断的是想让它的预测结果和实际值更小这个叫loss functio之前课程中我们一直跟loss打交道。多出来的结果叫y’, 和实际值的y之间, 我们会计算一个损失函数。
比如说我们要用用MSE做回归值(y’ - y)^2这等于它loss function。
所以正则化项意义就是对我们的叶子节点做了一惩罚项。 Ω ( f t ) γ T 1 2 λ ∑ j 1 T w j 2 \begin{align*} \Omega(f_t) \gamma T \frac{1}{2}\lambda \sum_{j1}^T w_j^2 \end{align*} Ω(ft)γT21λj1∑Twj2
整个 Ω ( f t ) \Omega (f_t) Ω(ft)用于控制树的复杂度防止过拟合使得模型更简化也使得最终的模型的预测结果更稳定。
这个复杂的公式里 T代表的就是叶子数量你想如果你的决策数叶子数量很多这个数模型就会很复杂。
w_j 是叶子分数的L2正则项 如果它的叶子的分数也是很大的话也比较复杂所以我们希望这棵树简单一点没有这么多的叶子节点而且叶子节点的数值也比较小一点。这样就是一个稍微小巧一点的模型。 γ \gamma γ是加入新叶子节点引入的复杂度代价。
那为什么要加正则化项呢我给大家举个场景你自己体会一下。我们的目标是希望损失函数最小化比如说我们目标是想要挣更多的钱有两种人a和b。a月薪是2万块钱他每天就是朝九晚五办公室的白领。b是网约车司机每天早上6点出门晚上12点回家他也是月薪2万块钱。
你想办公室的白领他的模型相对来说比较简单一点后面我们的系数就是大家不需要太多去努力大概读出来结果-1-0.11 0.1就好了。
网约车司机他会非常的奔波很累。可能这个系数抖动比较大最后得出结果10 20 -10 -20等等。
现在想一想同样月薪2万块钱你们希望是做a还是做b呢我们同样可以得到这样一个结果是希望是像办公室白领一样轻轻松松可以达到你的loss function这样的一个目标还是希望像网约车司机一样特别的辛苦很复杂。早上6点出门晚上是24点回家。那大部分人应该都是a这逻辑是一样的。
我们希望我们的那棵树没有那么的复杂也能达到比较好的效果。所以在我们的目标函数过程中统计了两个代价一个代价叫做loss function损失代价还有一个就是模型的代价。模型代价跟谁相关呢跟模型的叶子数和叶子的分数相关。 以上就把目标函数的两个过程损失函数和正则化项给大家讲完了。
接下来我们就详细的看一看它是怎么去做的。
预测函数样本的预测结果每棵树预测分数之和。 y ^ i ∑ k 1 k f k ( x i ) \begin{align*} \hat y_i \sum^k_{k1}f_k(x_i) \end{align*} y^ik1∑kfk(xi)
我们对目标函数进行优化 O b j ( Θ ) ∑ i l ( y i , y ^ i ) ∑ k Ω ( f k ) Ω ( f ) γ T 1 2 λ ∣ ∣ w ∣ ∣ 2 \begin{align*} Obj(\varTheta) \sum_il(y_i, \hat y_i)\sum_k\Omega(f_k) \\ \Omega(f) \gamma T \frac{1}{2}\lambda ||w||^2 \end{align*} Obj(Θ)Ω(f)i∑l(yi,y^i)k∑Ω(fk)γT21λ∣∣w∣∣2
我们在原来的loss function里面加了一个正则化项下面的那个是正则化项的公式前面是叶子节点的数量后面是叶子节点的分数。我们希望目标函数最小化把这个目标函数写成以下的一个过程 O b j t ∑ i 1 n l ( y i , y ^ i t − 1 f t ( x i ) ) Ω ( f t ) c o n s t a n t \begin{align*} Obj^t \sum_{i1}^n l(y_i, \hat y_i^{t-1} f_t(x_i))\Omega(f_t) constant \end{align*} Objti1∑nl(yi,y^it−1ft(xi))Ω(ft)constant
集成学习的树是由多棵树来完成的如果你现在做的是t棵树前面那个结果就是t-1棵树。t-1棵树的结果加上 Δ \varDelta Δ也就是 f t ( x i ) f_t(x_i) ft(xi)就说第t棵树的结果。之前咱们说的model1, model2, model3这是三棵树, 如果t等于3的话前面两棵树是t-1预测结果加上第三棵树的预测结果。
这两个过程我们都是拿它做一个loss function的一个组合再加上正则化项再加上一个常数项这等它的目标函数。
对这个函数改进进行二阶泰勒展开 f ( x Δ x ) ≈ f ( x ) f ′ ( x ) Δ x 1 2 f ′ ′ ( x ) Δ x 2 \begin{align*} f(x\varDelta x) \approx f(x) f(x)\varDelta x \frac{1}{2} f(x)\varDelta x^2 \end{align*} f(xΔx)≈f(x)f′(x)Δx21f′′(x)Δx2
那关于泰勒展开我在数学基础篇里有一篇专门来讲这个。现在我们只要知道它是一个定理这个定理就是说你的变量 x Δ x x\varDelta x xΔx可以近似的把它展开出来这样。 y ^ i ( 0 ) 0 y ^ i ( 1 ) f 1 ( x i ) y ^ ( 0 ) f 1 ( x i ) y ^ i ( 2 ) f 1 ( x i ) f 2 ( x i ) y ^ ( 1 ) f 2 ( x i ) ⋯ y ^ i ( t ) ∑ k 1 t f k ( x i ) y ^ i ( t − 1 ) f t ( x i ) \begin{align*} \hat y_i^{(0)} 0 \\ \hat y_i^{(1)} f_1(x_i) \hat y^{(0)} f_1(x_i) \\ \hat y_i^{(2)} f_1(x_i) f_2(x_i) \hat y^{(1)} f_2(x_i) \\ \cdots \\ \hat y_i^{(t)} \sum_{k1}^tf_k(x_i) \hat y_i^{(t-1)} f_t(x_i) \end{align*} y^i(0)y^i(1)y^i(2)⋯y^i(t)0f1(xi)y^(0)f1(xi)f1(xi)f2(xi)y^(1)f2(xi)k1∑tfk(xi)y^i(t−1)ft(xi)
那这个式子就可以这样推理得到。其中 y ^ i ( t ) \hat y_i^{(t)} y^i(t)是第t轮的模型预测 y ^ i ( t − 1 ) \hat y_i^{(t-1)} y^i(t−1)是保留前t-1轮的模型预测 而 f t ( x i ) f_t(x_i) ft(xi)是加入新的预测函数。
我们可以做多阶泰勒展开二阶泰勒展开呢相对简单一点。现在只要知道有这么一个概念这个概念是做一个近似的过程即可。今天就不去讲这个数学的推导了关于如何利用数学进行推导大家回到我数学篇里专门有一篇讲泰勒展开的一节去好好补一下基础。
那这个过程就还是一个loss function这里就是一个任何的function都是一样的。后面这个f’(x)是一个导数f’是一阶导数f’是二阶导数就是做完一阶以后再去做一阶。
一阶导数乘上 Δ x \varDelta x Δx再加上二阶导数乘上 Δ x 2 \varDelta x^2 Δx2这等于二阶泰勒展开这是一个定理。那这个定理代入的就是刚才这套过程。
我们来看定义
$$ \begin{align*} g_i \partial_{\hat y^{(t-1)}}l(y_i, \hat y^{(t-1)}) \ h_i \partial^2_{\hat y^{(t-1)}}l(y_i, \hat y^{(t-1)}) \
Obj^t \approx \sum_{i1}^n \left [ l(y_i, \hat y^{(t-1)}) g_if_t(x_i) \frac{1}{2}h_if_t^2(x_i) \right ] \Omega(f_t) constant \end{align*} $$
这里f(x)就是等于 l ( y i , y ^ i ( t − 1 ) ) l(y_i, \hat y_i^{(t-1)}) l(yi,y^i(t−1))后面这个 f t ( x i ) f_t(x_i) ft(xi)不就是 Δ x \varDelta x Δx吗然后f’(x)是定义成了一阶导数用g来代表再之后是 Δ x 2 \varDelta x^2 Δx2它就是 f t 2 ( x i ) f_t^2(x_i) ft2(xi)。那个二阶导数用h来代表前面再把1/2拿过来。
这样目标函数我们就把它做了个改写我们把它用二阶泰勒展开做了个改写中间的一阶导数项用g二阶导数项用h所以它是个约等于。
有了这个流程以后刚才这是个约等于是用二阶泰勒展开。还可以再去详细的去看一看, f_t(x_i)这是第7棵树的结果因为咱们用的是个决策树它的结果是在叶子节点那么叶子节点可以作为定义。它叶子节点假设是w那它的叶子节点的平方也是w的平方我们再加上后面的正则化项正则化项是刚刚我们定义好的 γ T λ 1 2 ∑ i 1 T w j 2 \gamma T\lambda\frac{1}{2}\sum_{i1}^T w_j^2 γTλ21∑i1Twj2, 这是陈天奇定义好的一个公式。这样一个推导我们还可以再把它去做一个合并的过程,这个过程就不完全展开了可以自己看一下我们来看一个完整的推导 O b j t ∑ i 1 n [ g i f t ( x i ) − 1 2 h i f t 2 ( x i ) ] Ω ( f t ) ∑ i 1 n [ g i w q ( x i ) 1 2 h i w q ( x i ) 2 ] γ T λ 1 2 ∑ i 1 T w j 2 ∑ j 1 T [ ( ∑ i ∈ I j g i ) w j 1 2 ( ∑ i ∈ I j h i λ ) w j 2 ] γ T \begin{align*} Obj^t \sum_{i1}^n \left [ g_if_t(x_i) - \frac{1}{2}h_if_t^2(x_i) \right ] \Omega(f_t) \\ \sum_{i1}^n \left [ g_iw_{q(x_i)} \frac{1}{2} h_iw^2_{q(x_i)} \right ] \gamma T \lambda\frac{1}{2}\sum_{i1}^T w_j^2 \\ \sum_{j1}^T \left [\left( \sum_{i\in I_j} g_i \right) w_j \frac{1}{2} \left ( \sum_{i\in I_j} h_i \lambda \right ) w_j^2 \right] \gamma T \end{align*} Objti1∑n[gift(xi)−21hift2(xi)]Ω(ft)i1∑n[giwq(xi)21hiwq(xi)2]γTλ21i1∑Twj2j1∑T i∈Ij∑gi wj21 i∈Ij∑hiλ wj2 γT
T为叶子节点数量 I j I_j Ij定义为每个叶子节点里面的样本集合 I j { i ∣ q ( x i ) j } I_j \{ i | q(x_i) j \} Ij{i∣q(xi)j} f t ( x i ) w q ( x i ) f_t(x_i) w_{q(x_i)} ft(xi)wq(xi)即每个样本所在叶子节点索引的分数叶子权重w。
那么我们就可以看到g是做了一个求和项,h也做了一个求和项。 所以我们就把一阶导数的求和用一个大G去表达 G j ∑ i ∈ I j g i G_j \sum_{i\in I_j} g_i Gj∑i∈Ijgi二阶的求和用个大H来做表达 H j ∑ i ∈ I j h i H_j \sum_{i\in I_j} h_i Hj∑i∈Ijhi就是把这个过程用大G和大H来去做一个表达那我们上面最后那一步的那个复杂公式就可以写成 O b j t ∑ j 1 T [ G j w j 1 2 ( H j λ ) w j 2 ] γ T \begin{align*} Obj^t \sum_{j1}^T \left[ G_jw_j \frac{1}{2}(H_j \lambda) w_j^2 \right] \gamma T \end{align*} Objtj1∑T[Gjwj21(Hjλ)wj2]γT
以上就把它的目标函数做了一个改写, 那现在我们是希望这个目标函数是越大越好还是越小越好自然是希望它越小越好。那什么时候得到最小值导数为0的时候就是对 ∂ O b j ∂ w j \frac{\partial Obj}{\partial w_j} ∂wj∂Obj求偏导那求偏导就得到 ∂ O b j ∂ w j G j ( H j λ ) w j 0 \begin{align*} \frac{\partial Obj}{\partial w_j} G_j (H_j \lambda)w_j 0 \end{align*} ∂wj∂ObjGj(Hjλ)wj0
导数等于0的时候我们就可以求到极值它等于0的时候我们可以求解得 w j − G j H j λ O b j − 1 2 ∑ j 1 T G j 2 H j λ γ T \begin{align*} w_j - \frac{G_j}{H_j \lambda} \\ Obj -\frac{1}{2} \sum_{j1}^T \frac{G_j^2}{H_j \lambda} \gamma T \end{align*} wjObj−HjλGj−21j1∑THjλGj2γT
先求得 w j w_j wj之后再将它代入到前面那个公式我们就可以得到Obj。
所以要想让目标函数最小我们可以直接求出来w_j的极值以及最小化的那个Obj。
有了这个过程之后我们一起看一看我们的XGBoost是怎么去进行运算的。
我们的Obj的目标函数也是称为一个叫结构分数打分函数我们希望这个结构分数越小越好。越小就代表它这个结构越稳定。 我们看图第一个部分判断is male为yes的时候的叶子是一个样本为no的时候是一个样本那判断age 15为no的时候是三个样本。如果三个样本输出的结果的话我们的的大G就是三个样本的之和大H也是这三个样本的h二阶导数之和。
Obj是衡量模型好坏的标准我们希望这个分数越小越好就是这个数会更加的稳定一些。
那怎么样去求解这个Obj让它更小刚才我们已经找到了这个机制也就是 O b j − 1 2 ∑ j 1 T G j 2 H j λ γ T \begin{align*} Obj -\frac{1}{2} \sum_{j1}^T \frac{G_j^2}{H_j \lambda} \gamma T \end{align*} Obj−21j1∑THjλGj2γT
这样Obj会比较好一点。那我们的树要去做分割大家知道这个学习过程中的树是一点点长出来的长出来的话叶子节点做分割就会成为一个父亲和孩子的一个结构。那要不要做分割的依据是啥孩子的Obj应该要更小一点才会更好。所以你要去做的事情我们把它称为叫做一个GainGain就是你分割的一个条件。 G a i n 1 2 [ G L 2 H L λ G R 2 H R λ − ( G L G R ) 2 H L H R λ ] − γ \begin{align*} Gain \frac{1}{2}\left[ \frac{G_L^2}{H_L \lambda} \frac{G_R^2}{H_R \lambda} - \frac{(G_L G_R)^2}{H_L H_R \lambda}\right ] - \gamma \end{align*} Gain21[HLλGL2HRλGR2−HLHRλ(GLGR)2]−γ
这个式子中的几个部分如下 Gain等于父亲啊减去孩子也就是分割前的Obj减去分割后的左右Obj。如果说父亲的Obj减去孩子的Obj等于Gain那么Gain如果小于0还要不要做分割那么要记得Gain0, 那说明孩子比父亲还不稳定那这个节点就不做分割我们要找Gain0的点。那Gain0也有很多我们要找其中最大的来做分割。这是XGBoost的一个过程。
那这里的可能性多不多我们怎么做分裂节点的分裂我们以这五个样本为例 这是一个叶子节点这叶子节点里面要去给它做分裂先按照原来的g_i, 就是一阶的导数从小到大来做个排序按照一定的顺序。
那g1, g4的顺序实际上就是g1比g4要小后面也是。按照这个顺序来做排序排序以后我们现在切分有几种切分的方法如果是5个样本的话从最前面和最后面分割毫无意义我们要做的是从中间将它们一分为二那无非就是[[1,4], [2, 3], [3, 2], [4, 1]]。所以应该是四种结构。
我们有四种分裂的可能性我们要找这种分裂的Obj最小的, 或者叫Gain最大的。四种结构我们要求4个Gain, 在四个里面去找到一种最大的来去做判断。
我们知道我们的样本数有可能很多一般机器学习有可能有上万个样本。一个节点最开始原来样本假设有1万个想想1万个这样的样本要把它做划分的话现在还是用从小到大给它规范好这样的顺序来做划分有多少种划分方式呢要计算1w-1次接近1万次9,999次。
这只是划分一次决策树的划分不仅仅分裂一次分裂完一次以后下个节点还可以再做分裂。所以每次来计算的话这个计算量相当于是个for循环一样计算量其实是蛮大的。
这是我们最开始的XGBoost的版本对于它的节点划分来说我们要计算1w - 1次, 如果它的这个节点的样本是1w的话。 原始的XGBoost的计算量会比较大这是在2014年的版本。XGBoost的原理在2014年提出来用的是一种贪心算法。这个贪心是从小到大的顺序来做了一个规范化其实整个的顺序是有多种可能性的我们是按照从小到大的顺序。然后去切的过程中我们也只是看当下自有解这是贪心计算方法。
但即使这种计算方法的计算量级也很多在2016年作者就提出来一种改进的方式叫做histogram。 它用直方图其目的就是把多个样本给它捆绑到一起。我们还是要做一个分裂的事情再看刚才的结果如果你在叶子节点上有1万个样本原来是要切分出来9,999刀现在把这1万个样本用绳子给它捆绑出来128个桶。桶就是一个最小的单位把前面这些样本都拿绳子捆到一起后面这个捆到一起一共有多少桶128个桶。
我们如果再去做切分的时候只能在桶与桶之间来做切分那它的划分的样式有多少种原来的1万要做9,999次的切分现在128个桶在做计算的时候就变成了127次。这种方式是种降维处理有点类似于像聚类的方式这样我们的计算量就大大缩减所以他的计算的时间就会快很多。
这是XBGoost的一种近似的方法近似的方法它不代表好但是它是属于近似最优解可以用更快的时间提升基本上快几十倍还是有可能的。
以上就是XGBoost的原理我们简单的再总结一下。
XGBoost是在GBDT多棵集成学习树上面做的优化。多棵学习树可以把它理解成model1model2…modeln, 这是原来的集成学习的概念。XGBoost在原有基础上加了正则化项正则化项的目的是防止过拟合。同时这个正则化项构造的很精巧它用了一个公式这个公式带进去以后经过一系列的转化它的二阶项跟前面的1/2就消掉了。转化以后通过求偏导的方式可以把极值给求出来。前后相减的分裂过程是希望孩子的Obj更小。也就是说我们的父亲的Obj减去孩子的Obj等于Gain每一项的话都可以进行一个求解我们希望它的Gain变得更大一点。
那么怎么做分裂呢就会有尝试多种分裂的方法找到一种更最大的分裂方式。在这么多种分裂方法过程中采用的是贪心算法1万个样本就要切1万减1刀。作者在2016年提出来了更快的方法就是直方图的方法这方法可以按照桶的个数来进行划分所以它是一种近似的方式。
XGBoost算法的一些特点呢就是讲树模型的复杂度加入到正则项中从而避免过拟合泛化性能好。其损失函数是用泰勒展开去完成的用到了一阶和二阶导数可以加快优化速度。它在寻找最佳分割点的时候采用的是近似贪心算法用来加速计算。那直方图还可以使用GPU来进行计算GPU就可以采用并性化的方式来进行计算所以速度就会比较快。XGBoost不仅支持CART作为基分类器还支持线性分类器在使用线性分类器的时候可以使用L1 L2正则化。
XGBoost有点是速度快、效果好、能处理大规模数据、支持自定义损失函数等缺点就是算法参数过多调参复杂不适合处理超高维度特征数据。
XGBoost的通用参数
booster[defaultgbtree] 模型选择gbtree或者gblinear。gbtree使用基于树的模型进行提升计算gblinear使用线性模型进行提升计算。。silent[default0]缄默方式0表示打印运行时信息1表示以缄默方式运行不打印运行时信息。nthread[default缺省值是当前系统可以获得的最大线程数]XGBoost运行时的线程数。num_feature boosting过程中用到的特征个数XGBoost会自动设置。eta[default0.3] 为了防止过拟合更新过程中用到的收缩步长。在每次提升计算之后算法会直接获取新特征的权重。eta通过缩减特征的权重使提升计算过程更加保守取值范围为[0, 1]。gamma[default0], 分裂节点时损失函数减小值只有大于等于gamma节点才分裂gamma值越大算法越保守越不容易过拟合但性能就不一定能保证需要trade off 取值范围[0, ∞]。max_depth[default6] 树的最大深度取值范围为[1, ∞], 典型值为3-10。min_child_weight[default1]一个自己的所有观察值的最小权重和。如果新分裂的节点的样本权重和小于min_child_weight则停止分裂。这个可以用来减少过拟合但是也不能太高会导致欠拟合取值范围为[0, ∞]。subsample[default1], 构建每颗树对样本的采样率如果设置成0.5 XGBoost会随机选择50%的样本作为训练集。colsample_bytree[default1]列采样率也就是特征采样率。lambda[default1, alias:reg_lambda], L2正则化用来控制XGBoost的正则化部分alpha[default0, alias:reg_alpha]L2正则化增加该值会让模型更加收敛。scale_pos_weight[default1], 在类别高度不平衡的情况下将参数设置大于0可以加快收敛。
学习目标参数
objective[defaultreg:linear]定义学习目标reg:linearreg:logisticbinary:logisticbinary:logitrawcount:poissonmulti:softmax multi:softprobrank:pairwiseeval_metric评价指标包括rmseloglosserrormerrormloglossaucndcgmap等seed[default0]随机数的种子dtrain训练的数据num_boost_round提升迭代的次数也就是生成多少基模型early_stopping_rounds早停法迭代次数evals这是一个列表用于对训练过程中进行评估列表中的元素。形式是evals [(dtrain,‘train’),(dval,‘val’)]或者是evals [(dtrain,‘train’)] 对于第一种情况它使得我们可以在训练过程中观察验证集的效果verbose_eval如果为True则对evals中元素的评估输出在结果中如果输入数字比如5则每隔5个迭代输出一次 nm - learning_rates每一次提升的学习率的列表
我们看这个参数量还挺多的XGBoost里面参数量确实还是比较多的如果你用到的话可以回头再来看看我这篇文章当作一个手册来看。默认情况下了我会教给大家一些比较常见的参数设置你直接用它就可以。
我这里还是给大家看一个示例
# 天猫用户复购预测XGBoost使用示意
X_train, X_valid, y_train, y_valid train_test_split(train_X, train_y, test_size.2)# 使用XGBoost
model xgb.XGBClassifier(max_depth 8, # 树的最大深度n_estimators 1000, # 提升迭代的次数也就是生成多少基模型min_child_weight 300, # 一个子集的所有观察值的最小权重和colsample_bytree 0.8, # 列采样率也就是特征采样率subsample 0.8, # 构建每颗树对样本的采样率eta 0.3, # eta通过缩减特征的权重使提升计算过程更加保守防止过拟合seed 42 # 随机数种子
)model.fit(X_train, y_train,eval_metricauc, eval_set[(X_train, y_train), (X_valid, y_valid)],verboseTrue,# 早停法如果auc在10epoch没有进步就stopearly_stopping_rounds 10)
model.fit(X_train, y_train)
prob model.predict_proba(test_data)比如我们现在创建好了一个model XGBClassifier创建好之后我们可以设置参数比如一些树的深度等:
param {boosting_type:gbdt, objective:binary:logistic, # 任务目标eval_metric:auc, # 评估指标eta:0.01, # 学习率max_depth:15, #树最大深度colsample_bytree:0.8, #设置在每次迭代中使用特征的比例subsample: 0.9, #样本采样比例subsample_freq: 8, #bagging的次数alpha: 0.6, #L1正则lambda: 0, #L2正则
}colsample和subsample, 这个分别代表我们的列采样和行采样。设置行采样和列采样是让我们每次训练的时候更加的快一点更加的轻量一点。这两个参数和树的深度参数这三个参数都是比较常见的需要设置的参数。此外我们还需要针对你的任务来去做设置任务目标。
我们以attraction这个题目为例可以看一看怎么用
train_data xgb.DMatrix(X_train, labely_train)
valid_data xgb.DMatrix(X_valid, labely_valid)
test_data xgb.DMatrix(test) model xgb.train(param, train_data, evals[(train_data, train), (valid_data, valid)], num_boost_round 10000, early_stopping_rounds200, verbose_eval25) predict model.predict(test_data)
test[Attrition]predict # 转化为二分类输出
test[Attrition]test[Attrition].map(lambda x:1 if x0.5 else 0)
test[[Attrition]].to_csv(dataset/submit_lgb.csv)原来的XGBoost还有两种版本, 一种版本的话是用它的DMatrix这属于官方封装好的一个结构。 把原来切分好的数据集用DMatrix来做的一个封装封装好以后再进行训练。所以它是属于一个自己的一个训练的一个数据结构叫DMatrix。我们以前用训练的话一般用fit 如果你用XGBoost官方版本的话它写的是train这是它的一个写法会稍微有一些区别。
带进去之后其实后面都是调包的过程train完以后predict得到一个结果最后把这个结果进行输出。
那我们来去用XGBoost来完成一下上节课我们完成的项目首先还是数据的一些处理这个和我们前几节课没有什么不同。主要就是我们要对一个参数进行设置
param {boosting_type: gbdt,objective: binary:logistic,eval_metric: auc,eta: 0.01,max_depth: 15,colsample_bytree: 0.8,subsample: 0.9,subsample_freq: 8,alpha: 0.6,lambda:0
}这个就比我们之前调用其他模型来进行计算的参数量多了很多。然后我们用它官方的结构DMatrix
train_data xgb.DMatrix(X_train, labely_train)
valid_data xgb.DMatrix(X_valid, labely_valid)
test_data xgb.DMatrix(test)这个套用就是把X_trainy_train给它放进去它会封装一个自己的数据结构。所有样本都是一样放进去训练的话就用自己的数据结构来去做训练。
model xgb.train(param, train_data, evals[(train_data, train), (valid_data, valid)], num_boost_round10000, early_stopping_rounds200, verbose_eval25)param是前面设置好的我们的训练的一些参数设置成一个字典这是常见的一些配置。训练以后就可以拿这个模型去做预测得到一个预测结果再把这个结果进行输出。
predict model.predict(test_data)
test[Attrition] predict
print(predict)---
[25] train-auc:0.98897 valid-auc:0.75885
...
[675] train-auc:1.00000 valid-auc:0.77299
[0.11253858 0.07342984 0.19541897 0.11211961 0.8137899 0.19079192
...0.07080463 0.07864323 0.09115468 0.21122025 0.06211422 0.06264106]我们打印的结果来看发生了过拟合的情况。在做训练过程中我们加了一个validation现在train-auc和valid-auc都有一个评分。现在呢训练集基本满分但是验证集和它差别很大。
这种情况下我们就可以调整参数来防止过拟合状况。那我们首当其冲应该想到的就是eta以及max_depth 深度过大会造成过拟合eta本来就是为了防止过拟合而在更新过程中用到的收缩步长。
在进行调整之后过拟合状况就好多了
[290] train-auc:0.91738 valid-auc:0.83852下一节课我们来看看Boosting的另外一个版本微软出的LightBGM.