Xgboost

在最近的 Kaggle 竞赛中,利用 Xgboost 的队伍经常能问鼎冠军,那么问题来了,Xgboost 为什么这么强呢?

算法释义

Xgboost 是一种带有正则化项,并利用损失函数泰勒展开式中二阶导数信息优化求解并增加一些计算优化的梯度提升树。Xgboost 的目标函数定义为:

其中 l 为损失函数, Ω(ft(x)) 是用于惩罚 ft(x) 模型复杂度的正则化项。根据上述目标函数可以得到 Xgboost 在每一轮前向分步算法中的目标函数为:
\begin{align} & Obj^{(t)} = \sum_{i=1}^N l(y_i, \hat y_i^{(t-1)} + f_t(x_i)) + Ω(f_t(x)) + constant\\ &联想二级泰勒展开式:\\ &f(x_0 + x) = f(x_0) + f'(x_0)x + \frac 1 2 f''(x_0)x^2 \\ & 令其中\, f(x) = l(y_i, \hat y_i^{(t-1)}), x_0 = \hat y_i^{(t-1)},x = f_t(x_i): \\ & 再令:g_i = l'(y_i, \hat y_i^{(t-1)}), h_i = l''(y_i, \hat y_i^{(t-1)}),并去除常数项: \\ & Obj^{(t)} = \sum_{i=1}^N \left(g_i f_t(x_i) + \frac 1 2 h_i f_t^2(x_i) \right) + Ω(f_t(x)) \\ \end{align}

从而每一步的目标函数可以用损失函数的一阶导数和二阶导数来表示,这样每一轮需要求解的 ft(x) 为:

那么如何使目标函数最小化呢?


算法求解

Xgboost 每生成一颗树的方式和其他决策树的方式类似,采用一种贪心策略。
我们知道一颗决策树可以表示为:

其中 q(x) 把 x 映射到决策树中的一个节点,wq 把每一个结点映射一个值,即 ft(x) 的取值。
\begin{align} & 令I_j表示结点j,即: I_j = \{i| q(x_i) = j\} \\ & 然后取正则化项:\\ & Ω(f_t(x)) = γT + \frac 1 2 λ \sum_{j=1}^T w_j^2 \\ & 其中\,T\,为叶节点个数 \\ & 目标函数Obj^{(t)}可以化为: \\ & Obj^{(t)} = \sum_{j=1}^T \left(w_j\sum_{i \in I_j} g_i + \frac 1 2 w_j^2 \sum_{i \in I_j} h_i \right) + Ω(f_t(x)) \\ & 即:\\ &Obj^{(t)} = \sum_{j=1}^T \left(w_j\sum_{i \in I_j} g_i + \frac 1 2 w_j^2 \left(λ + \sum_{i \in I_j} h_i \right) \right) + γT \\ \end{align}

我们知道上述目标函数中有权重 w 以及树的节点数量 T 两组变量,首先上式可以拆分为 T 个独立的二次函数最小化问题,每个子问题中只有 w 权重这一组变量,首先求解权重 w。

权重求解

因为二次函数最小化问题有解析解,所以直接求解:
\begin{align} & w_j^* = - \frac {\sum_{i \in I_j} g_i} {λ + \sum_{i \in I_j} h_i} \\ & 令 G_j = \sum_{i \in I_j} g_i, H_j = \sum_{i \in I_j} h_i,则 \\ & w_j^* = - \frac {G_j} { H_j + λ } \\ & 那么在最优解 w_j^*的情况下子问题和母问题的目标函数分别为: \\ & Obj_j = - \frac {G_j^2} {2(H_j + λ)} \\ & Obj = - \frac 1 2 \sum_{j=1}^T \frac {G_j^2} {H_j + λ} + γT \\ \end{align}

树的生成

解决了权重求解的问题,如何解决结点数量问题呢?也就是说怎么样对结点进行划分呢?这里一般在每个节点上采用贪心策略进行划分。通过比较划分前和划分后目标函数的减少量来选择最优划分属性和划分点,具体地:

减少树的权重

使用 Xgboost 没生成一棵决策树时,更新 y(t)(x) 时:

一般采用较小的 ε 值,例如 0.1,这样可以防止在某一轮“学得太好”,并且为未来的迭代提供“学习空间”,可以有效地防止过拟合。


参考资料

《Xgboost PPT》,陈天奇

你可能感兴趣的:(Xgboost)