【机器学习10】XGBoost

分享 未结 0 695
你的瓦刀
你的瓦刀 站长 2020年3月28日 21:45 编辑
点击群号免费加入尼特社区交流群:813128395
<p id="descriptionP"><p>&nbsp; &nbsp; &nbsp; &nbsp; 在竞赛题中经常会用到<span style="color: rgb(255, 0, 0);">XGBoost</span>算法,用这个算法通常会使我们模型的准确率有一个较大的提升。既然它效果这么好,那么它从头到尾做了一件什么事呢?以及它是怎么样去做的呢?<br>&nbsp; &nbsp; &nbsp; &nbsp; 我们先来直观的理解一下什么是XGBoost。<span style="font-weight: bold;">XGBoost算法是和决策树算法联系到一起的</span>。</p><p><br></p><h2>一、集成算法思想</h2><p>&nbsp; &nbsp; &nbsp; &nbsp; 在决策树中,我们知道一个样本往左边分或者往右边分,最终到达叶子结点,这样来进行一个分类任务。 其实也可以做回归任务。</p><p><img src="https://qcdn2.niter.cn/upload/user/98/img/20200328213945_cpzrg.png" style="max-width:100%;"><br></p><p>&nbsp; &nbsp; &nbsp; &nbsp;看上面一个图例左边:有5个样本,现在想看下这5个人愿不愿意去玩游戏,这5个人现在都分到了叶子结点里面,<span style="font-weight: bold;">对不同的叶子结点分配不同的权重项</span>,正数代表这个人愿意去玩游戏,负数代表这个人不愿意去玩游戏。所以我们可以通过叶子结点和权值的结合,来综合的评判当前这个人到底是愿意还是不愿意去玩游戏。上面「tree1」那个小男孩它所处的叶子结点的权值是+2(可以理解为得分)。<br>&nbsp; &nbsp; &nbsp; 用单个决策树好像效果一般来说不是太好,或者说可能会太绝对。通常我们会用一种集成的方法,<span style="font-weight: bold;">就是一棵树效果可能不太好,用两棵树呢?</span><br>&nbsp; &nbsp; &nbsp; 看图例右边的「tree2」,它和左边的不同在于它使用了另外的指标,出了年龄和性别,还可以考虑使用电脑频率这个划分属性。通过这两棵树共同帮我们决策当前这个人愿不愿意玩游戏,小男孩在「tree1」的权值是+2,在「tree2」的权值是+0.9, 所以小男孩最终的权值是+2.9(可以理解为得分是+2.9)。老爷爷最终的权值也是通过一样的过程得到的。<br>&nbsp; &nbsp; &nbsp; 所以说,我们通常在做分类或者回归任务的时候,需要想一想一旦选择用一个分类器可能表达效果并不是很好,那么就要考虑用这样一个集成的思想。上面的图例只是举了两个分类器,其实还可以有更多更复杂的<span style="color: rgb(255, 0, 0);">弱分类器,一起组合成一个强分类器</span>。<br><br></p><h2>二、XGBoost基本思想</h2><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;XGBoost的集成表示是什么?怎么预测?求最优解的目标是什么?看下图的说明你就能一目了然。</p><p><img src="https://qcdn2.niter.cn/upload/user/98/img/20200328214548_x34wl.png" style="max-width:100%;"><br></p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;在XGBoost里,<span style="font-weight: bold;">每棵树是一个一个往里面加的</span>,每加一个都是希望效果能够提升,下图就是XGBoost这个集成的表示(核心)。</p><p><img src="https://qcdn2.niter.cn/upload/user/98/img/20200328214058_adboc.png" style="max-width:100%;"><br></p><p>&nbsp; &nbsp; &nbsp; &nbsp;一开始树是0,然后往里面加树,相当于多了一个函数,再加第二棵树,相当于又多了一个函数...等等,<span style="font-weight: bold;">这里需要保证加入新的函数能够提升整体对表达效果</span>。提升表达效果的意思就是说加上新的树之后,目标函数(就是损失)的值会下降。</p><p>&nbsp; &nbsp; &nbsp; &nbsp;如果叶子结点的个数太多,那么过拟合的风险会越大,所以这里要限制叶子结点的个数,所以在原来目标函数里要加上一个惩罚项「<span style="font-weight: bold;">Ω(ft)</span>」。</p><p><img src="https://qcdn2.niter.cn/upload/user/98/img/20200328214154_4viog.png" style="max-width:100%;"><br></p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;这里举个简单的例子看看惩罚项「<span style="font-weight: bold;">Ω(ft)</span>」是如何计算的:</p><p><img src="https://qcdn2.niter.cn/upload/user/98/img/20200328214213_t06ty.png" style="max-width:100%;"><br></p><p>&nbsp; &nbsp; &nbsp; &nbsp; 一共3个叶子结点,权重分别是2,0.1,-1,带入「Ω(ft)」中就得到上面图例的式子,惩罚力度和「<span style="font-weight: bold;">λ</span>」的值人为给定。<br><br>&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: rgb(255, 0, 0);">XGBoost算法完整的目标函数</span>见下面这个公式,它由<span style="color: rgb(255, 0, 0);">自身的损失函数</span>和<span style="color: rgb(255, 0, 0);">正则化惩罚项</span>「Ω(ft)」相加而成。</p><p><img src="https://qcdn2.niter.cn/upload/user/98/img/20200328214237_sxrd2.png" style="max-width:100%;"><br></p><p>&nbsp; &nbsp; &nbsp; &nbsp;关于目标函数的推导本文章不作详细介绍。过程就是:给目标函数对权重求偏导,得到一个能够使目标函数最小的权重,把这个权重代回到目标函数中,这个回代结果就是<span style="font-weight: bold;">求解后的最小目标函数值</span>,如下:</p><p><img src="https://qcdn2.niter.cn/upload/user/98/img/20200328214305_talc6.png" style="max-width:50%;"></p><p><img src="https://qcdn2.niter.cn/upload/user/98/img/20200328214305_okrj4.png" style="max-width:50%;"><br></p><p><img src="https://qcdn2.niter.cn/upload/user/98/img/20200328214352_hveej.png" style="max-width:100%;"><br></p><p>&nbsp; &nbsp; &nbsp; &nbsp; 其中第三个式子中的一阶导二阶导的<span style="font-weight: bold;">梯度数据</span>都是可以算出来的,只要指定了主函数中的两个参数,这就是一个确定的值。下面给出一个直观的例子来看下这个过程。</p><p><img src="https://qcdn2.niter.cn/upload/user/98/img/20200328214423_01vby.png" style="max-width:100%;"><br></p><p>&nbsp; &nbsp; &nbsp; &nbsp;(这里多说一句:Obj代表了当我们指定一个树的结构的时候,在目标上最多会减少多少,我们可以把它叫做结构分数,<span style="font-weight: bold;">这个分数越小越好</span>)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;对于每次扩展,我们依旧要<span style="font-weight: bold;">枚举所有可能的方案</span>。对于某个特定的分割,我们要计算出这个分割的左子树的导数和和右子数导数和之和(就是下图中的第一个红色方框),然后和划分前的进行比较(基于损失,看分割后的损失和分割前的损失有没有发生变化,变化了多少)。<span style="color: rgb(255, 0, 0);">遍历所有分割,选择变化最大的作为最合适的分割</span>。</p><p><img src="https://qcdn2.niter.cn/upload/user/98/img/20200328214451_y28xc.png" style="max-width:100%;"><br></p><h2>三、安装XGBoost</h2><p>可自行百度</p><p><br></p><h2>四、用python实现XGBoost算法</h2><p>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<a href="https://pan.baidu.com/s/12r19ySRkcaVCUQhw_vN2vw" target="_blank"><img style="height: 12px;" src="https://api.d5.nz/api/favicon/?url=https://pan.baidu.com/s/12r19ySRkcaVCUQhw_vN2vw">pima-indians-diabetes.csv</a>(提取码: qubw)文件中包括了8列数值型自变量,和第9列0-1的二分类因变量,导入到python中用XGBoost算法做探索性尝试,得到预测数据的准确率为77.95%。</p><pre><code>import xgboost<br>from numpy import loadtxt<br>from xgboost import XGBClassifier<br>from sklearn.model_selection import train_test_split<br>from sklearn.metrics import accuracy_score<br> <br># 载入数据集<br>dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",")<br># split data into X and y<br>X = dataset[:,0:8]<br>Y = dataset[:,8]<br> <br># 把数据集拆分成训练集和测试集<br>seed = 7<br>test_size = 0.33<br>X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=test_size, random_state=seed)<br> <br># 拟合XGBoost模型<br>model = XGBClassifier()<br>model.fit(X_train, y_train)<br> <br># 对测试集做预测<br>y_pred = model.predict(X_test)<br>predictions = [round(value) for value in y_pred]<br> <br># 评估预测结果<br>accuracy = accuracy_score(y_test, predictions)<br>print("Accuracy: %.2f%%" % (accuracy * 100.0))</code></pre><p>结果输出:<br></p><blockquote>Accuracy: 77.95%</blockquote><p>在python的XGBoost包中最重要的函数是XGBClassifier(),函数中涉及到多种参数,此外还可以关注plot_importance(),更多的说明我将在以后进行更新。<br></p><p></p><p><br></p><p>(<a href="https://blog.csdn.net/huacha__/article/details/81029680" target="_blank"><img style="height: 12px;" src="https://api.d5.nz/api/favicon/?url=https://blog.csdn.net/huacha__/article/details/81029680">参考链接</a>)</p></p>
收藏(0)  分享
相关标签: 机器学习 XGBoost 决策树 提升模型 boosting
注意:本文归作者所有,未经作者允许,不得转载
0个回复
  • 消灭零回复