前言:有监督算法的组成:模型,参数和目标函数
(1)模型:给入指定的Xi如何去预测Yi,姑且认为是一个Y关于X的函数吧,如线性回归Y=∑Wi*Xi
(2)参数:就是指系数W
(3)目标函数(损失+正则):目标函数的作用是找到比较好的参数W,来更好地预测,基本形式如下:
常见的误差函数有:
(1)平方误差:
(2)logistic误差函数:
正则化有L2和L1正则化(其区别可以看我另一篇博客)
XGBoost基本原理:实质上就是回归树(也称分类回归树,一下简称CART)的迭代算法。每迭代一次生成一颗CART,然后作者对算法的优化做了很多事情,下面会具体讲到,首先来讲一下CART举个经典的例子:
如图所示,我们需要判断一个人是否喜欢打游戏,已知age,gender,occupation等信息,假如只用一颗CART,如图所示的分裂方式,最终一个样本会被分到一个叶子结点中,对应着该叶子结点的值,对于二分类问题,该值通过sigmoid函数转化为概率,该概率表示分类为1的概率;对于回归问题,该值就是预测值。(单个树模型不考虑多分类问题)
(2)Tree Ensemble:多颗CART迭代
如图所示,对于一个样本,每棵树都会预测出一个结果(暂时称这个结果为分数),对于二分类问题来说,将所有树的分数相加,经过sigmoid转换,得到预测为1的概率;对于回归问题,将所有树的分数相加,得到的就是预测值。
很明显,xgboost的结果输出方式就是第二种,下面具体讲一下原理
xgboost目标函数形式为(training loss+正则项):
模型学习:additive training
模型训练过程:
还有一个问题,我们怎么加入f,以什么样的标准呢?我们的准则就是:选取一个f使得目标函数尽量最大的降低
可以把上面的公式写的具体一点:实际上就是把公式拆开,一步步来,很简单,
注:残差实际上就是每一轮的预测值和真实值的差,残差的使用面挺广的,也很有效,如ResNet在2015年就火了一把
有时候使用的不是平方误差,我们就用泰勒展开来近似目标函数,方便计算:
不考虑常数项,仔细看公式发现,中括号里面的表示误差函数,我们发现,好像就是在前一个误差函数下加上了一个一阶导数和二阶导数(实际上这就是泰勒公式的妙处)
这样可以得到什么呢?是不是意味着,我们前面得到了t-1个函数模型(树),我们要构建第t个模型(树)时,是不是只要求前t-1函数的一阶和二阶导数和前t-1的函数模型的乘积即可。这样是不是意味着我们不仅可以用这个模型来做分类,还可以回归等,增强了泛化性。
(4)树的复杂度:
前面我们讨论了目标函数的训练误差部分,接下来讨论如何定义树的复杂度。我们先对f的定义做一下细化,把树拆分成结构部分q和叶子权重部分w。结构函数q把输入映射到叶子的索引号上去,而w给定了每个索引号对应的叶子分数
我们定义一棵树的复杂度:这个复杂度包含了一棵树的节点数和每个叶子节点输出分数的模的平方(L2)。当然,不止这一种定义,如下:
看这个图应该还是比较好理解的
(5)关键步骤
我们可以对目标函数进行如下改写,其中I被定义为每个叶子节点上样本集合:
注:i代表第i个样本,j代表第j个叶子节点,整个代表在所有叶子节点上的样本的集合,集合的元素是单个叶子节点的样本的集合
上式包含了T(模型/树的个数)个相互独立的单变量二次函数,我们可以定义
那么目标函数又可以改写:只把w看成未知变量,假设树的结构我们知道
有了这个目标函数,我们可以很容易求w的最优解,直接对w求导
(6)打分函数举例(具体的表述待以后更新,楼主也不是很明白)
Obj代表了当我们指定一个树的结构的时候,我们在目标上面最多减少多少,
注:因为目标函数实际上是loss function,目的是为了逼近真实值,这里的分数就是Obj,实际上就是loss,当然是越小越好,这里的分数实际上每个树的评分
(7)枚举所有不同树结构的贪心算法
我们不断枚举树的结构,利用这个打分函数来寻找最优树,加入到我们的模型中,不断重复这个操作。不过这种枚举操作不太可行,所以常用贪心算法。每一次尝试去对已有的叶子加入一个分割。对于一个具体的分割方案,我们可以获得的增益可以由如下公式计算
对于每次扩展,我们还是要枚举所有可能的分割方案,如何高效地枚举所有的分割呢?我假设我们要枚举所有 x<a 这样的条件,对于某个特定的分割a我们要计算a左边和右边的导数和。
我们可以发现对于所有的aa,我们只要做一遍从左到右的扫描就可以枚举出所有分割的梯度和GL和GR。然后用上面的公式计算每个分割方案的分数就可以了。
观察这个目标函数,大家会发现第二个值得注意的事情就是引入分割不一定会使得情况变好,因为我们有一个引入新叶子的惩罚项。优化这个目标对应了树的剪枝, 当引入的分割带来的增益小于一个阀值的时候,我们可以剪掉这个分割。大家可以发现,当我们正式地推导目标的时候,像计算分数和剪枝这样的策略都会自然地出现,而不再是一种因为heuristic而进行的操作了。
讲到这里文章进入了尾声,虽然有些长,希望对大家有所帮助,这篇文章介绍了如何通过目标函数优化的方法比较严格地推导出boosted tree的学习。因为有这样一般的推导,得到的算法可以直接应用到回归,分类排序等各个应用场景中去。
centos系统下xgboost,python安装:
http://xgboost.readthedocs.io/en/latest/build.html#python-package-installation
参考链接:
1.XGBoost 与 Boosted Tree:http://www.52cs.org/?p=429