机器学习:提升树 GBDT
梯度提升树
提升树模型
在叙述梯度提升决策树模型 (GBDT, Gradient Boosting Decision Tree) 之前, 先叙述提升树模型 (BDT, Boosting Decision Tree).
在之前已经提到, 给定一个训练数据集 \(T = \{ (\mathbf{x}_1, y_1), (\mathbf{x}_2, y_2), \cdots, (\mathbf{x}_N, y_N) \}\), \(\mathbf{x}_i \in \mathcal{X} \subset \mathbb{R}^n\), \(\mathcal{X}\) 为输入空间, \(y_i \in \mathcal{Y} \subset \mathbb{R}\), \(\mathcal{Y}\) 为输出空间. 如果将输入空间划分为 \(J\) 个互不相交的区域 \(R_1, R_2, \cdots, R_J\), 并且在每个区域上确定输出的常量 \(c_j\), 那么决策树模型可以表示为:
其中, 参数 \(\Theta = \{ (R_1,c_1), (R_2,c_2),\cdots, (R_J,c_J) \}\) 表示树的区域划分和各区域上的常数输出值, \(J\) 是回归树的复杂度即叶节点个数. 也就是对训练集学习到一个空间的划分, 并且在每个划分中取不同的值 (若为回归树则为实数取值, 若为分类树则为整数取值).
以决策树为基函数的提升方法称为提升树 (boosting tree), 对分类问题决策树是二叉分类树, 对回归问题决策树是二叉回归树. 提升树模型可以表示为决策树的加法模型:
其中 \(T(\mathbf{x}; \Theta_m)\) 表示决策树, \(\Theta_m\) 为其参数, \(M\) 为树的个数. 提升树算法采用前向分步算法, 首先确定初始提升树 \(f_0(\mathbf{x}) = 0\), 则第 \(m\) 步的模型表示为:
其中, \(f_{m-1}(\mathbf{x})\) 是当前模型, 在每一轮迭代通过经验风险极小化确定下一个决策树的参数 \(\Theta_m\)
即在给定当前模型 \(f_{m-1}(\mathbf{x})\) 条件下求解下一个树的参数 \(\Theta = \{ R_{j}, c_{j}\}^{J}_{j=1}\).
需要注意的是提升树模型属于提升 (boosting) 方法, 但不是 Adaboost 方法. Adaboost 强调 adaptive, 在每一轮修改样本权值学习到不同的弱分类器. 而提升树模型强调不断减少残差, 在每一轮加入新的树在使残差减少方向 (负梯度) 上建立新的模型. 两种方法的 boosting 策略不同, 但都是采用加法模型与前向分步算法. 提升树模型没有在每个基分类器前面加上系数权值, 这是因为在每轮迭代过程生成的 \(T(\mathbf{x}; \Theta_m)\) 是对残差的拟合, 因此需要将其直接添加到之前的模型, 使得总残差越来越小.
回归问题提升树算法
对回归问题的提升树算法来说, 只需简单地拟合当前步模型的残差, 当采用平方误差损失函数时, 前向分步算法的每一轮求解参数等价于求解极小化损失函数:
其中 \(r = y_i - f_{m-1}(\mathbf{x})\) 是当前模型拟合数据的残差 (residual). 下面将回归问题的提升树算法 (最小二乘提升树) 叙述如下:
- 初始化 \(f_0(\mathbf{x}) = 0\), 在每一轮 \(m=1,2,\cdots,M\) 顺次执行以下操作:
- 计算残差
- 拟合残差学习一个回归树得到 \(T(\mathbf{x}; \Theta_m)\), 即求解参数 \(\Theta_m = \{ R_{jm}, c_{jm}\}^{J_m}_{j=1}\) (注意这里是先找到对应的节点划分区域 \(R_{mj}\), \(j=1,2,\cdots,J_m\), 然后求每个区域内的最佳拟合值 \(c_{mj}\), 即平均值)
- 更新
- 得到回归问题提升树
分类问题提升树算法
对于二类分类问题, 并指定损失函数为指数函数, 提升树算法只需要将 AdaBoost 算法中的基本分类器限制为二叉分类树 (CART 分类树) 即可, 此时的决策树算法可以直接利用之前的 AdaBoost 算法求解 (AdaBoost 算法形式是通过前向分步算法推导出来的).
不同问题的提升树学习算法主要区别在于使用的损失函数不同, 包括用平方误差损失函数的回归问题, 用指数损失函数的分类问题, 以及用一般损失函数的一般决策问题.
最速下降法
最速下降法以目标函数的负梯度作为极小化算法的下降方向, 它是无约束最优化中最简单的方法, 在欧式范数下, 最速下降法与梯度下降法等价. 具体来说, 设函数 \(f(x)\) 在 \(x_k\) 附近连续可微, 并且梯度 \(\nabla f(x_k) \neq 0\), 可由泰勒展开式将 \(f(x)\) 展开到一阶
记 \(x-x_k = \alpha_k d_k\), 若向量 \(d_k\) 满足 \(d_k^T \nabla f(x_k) < 0\), 则称 \(d_k\) 为 \(f(x)\) 在 \(x_k\) 处的一个下降方向, 另外这里的 \(\alpha_k\) 即为线性搜索步长. 可以证明, 负梯度方向 \(-\nabla f(x_k)\) 是函数 \(f(x)\) 在 \(x_k\) 处的一个下降方向. 令 \(d_k = -\nabla f(x_k)\), 还可以证明的是, \(d_k\) 是下面问题的解
实际上, 对任意 \(p \in \mathbb{R}^n\), \(||p||=1\), 由 Cauchy-Schwarz 不等式得
当 \(p=d_k=\frac{||\nabla f(x_k)||}{||\nabla f(x_k)||}\) 时, 上面的不等式成为等式, 由于 \(d_k\) 的上述性质, 称 \(d_k\) 为函数 \(f(x)\) 在 \(x_k\) 处的最速下降方向.
再求线性搜索步长 \(\alpha_k\)
由此便得到了一次最速下降步的更新
梯度提升框架
给定一个训练数据集 \(T = \{ (\mathbf{x}_1, y_1), (\mathbf{x}_2, y_2), \cdots, (\mathbf{x}_N, y_N) \}\), \(\mathbf{x}_i \in \mathcal{X} \subset \mathbb{R}^n\), \(\mathcal{X}\) 为输入空间, \(y_i \in \mathcal{Y} \subset \mathbb{R}\), \(\mathcal{Y}\) 为输出空间. 根据该训练数据集进行学习预测, 得到从 \(\mathbf{x}\) 到 \(y\) 的映射函数的一个估计 (或者说逼近) \(\hat{f}(\mathbf{x})\), 这个估计要在所有样本的联合分布上最小化某些特定的损失函数 \(L(y,f(\mathbf{x}))\) 的期望
这是在函数空间上的数值优化, 即将在每个点 \(\mathbf{x}\) 估计的 \(f(\mathbf{x})\) 作为一个参数最小化上面的目标函数, 或等价地, 在每个点 \(\mathbf{x}\) 直接关于 \(f(\mathbf{x})\) 最小化
一般将 \(f(\mathbf{x})\) 限制为含参函数族, 在梯度提升算法中考虑如下加法模型
上面加法模型中的基函数 (弱学习器或基学习器) \(b(\mathbf{x},\gamma_m)\) 是关于 \(\mathbf{x}\) 的带参函数, 例如当选择 CART 决策树模型, 那么参数 \(\gamma_m\) 包括作为分裂点的特征变量, 节点分裂的分裂值, 叶子节点的属性 (终止分裂的标准).
给定损失函数为 \(L(y,f(\mathbf{x}))\), 用如上加法模型 \(F_M(\mathbf{x})\) 把函数优化问题转化为如下参数优化问题
要学习加法模型 \(f_M(\mathbf{x})\) 使得预测值 \(f_M(\mathbf{x}_i)\) 尽可能地逼近真实值 \(y_i\), 这是针对所有 \(\{\beta_m,\gamma_m\}_{m=1}^M\) 的最优化问题, 采用前向分步算法 (forward stagewise algorithm) 在每一步贪婪地选择 \(\beta_m\) 和 \(\gamma_m\) 来逐步逼近目标函数式, 可以简化优化的复杂度. 即对于每一步 \(m=1,2,\cdots,M\), 优化问题可以改写为下面形式:
则可依次更新解的形式为
一般来说, 对于损失函数 \(L(y,f(\mathbf{x}))\) 和基函数 \(b(\mathbf{x},\gamma_m)\), 直接求解优化问题 \(\eqref{loss1}\) 是困难的. 假设给定了前 \(m-1\) 步的逼近函数 \(f_{m-1}(\mathbf{x})\), 在前向分布算法中得到的当前步子函数 \(\beta_m b(\mathbf{x},\gamma_m)\) 可以看作是在步方向 \(b(\mathbf{x},\gamma_m)\) 上对最优解函数 \(f^*(\mathbf{x})\) 的最佳贪婪逼近步, 这里的子函数 \(b(\mathbf{x},\gamma_m)\) 限制为含参函数族 \(b(\mathbf{x},\gamma)\) 的成员函数, 因此 \(\beta_m b(\mathbf{x},\gamma_m)\) 可以等同于最速下降法中的每一个更新步.
给定限制条件 \(f(\mathbf{x}) = f_{m-1}(\mathbf{x})\), 基于数据集的无约束负梯度形式如下
这里得到的梯度仅在训练数据集上定义, 而不能泛化到其他未知样本点. 一种泛化的方法是, 通过限制含参函数族 \(b(\mathbf{x},\gamma)\) 的成员函数 \(b(\mathbf{x},\gamma_m)\), 使其产生最平行于 \(-\mathbf{g}_m \in \mathbb{R}^N\) 的 \(\{b(\mathbf{x}_i,\gamma_m)\}^N_1\), 这里的 \(-\mathbf{g}_m\) 在数据分布上和 \(b(\mathbf{x},\gamma_m)\) 强相关, 可以通过下式求解:
用这里约束的负梯度 \(b(\mathbf{x},\gamma_m)\) 代替最速下降法中无约束的负梯度 \(-\mathbf{g}_m\), 得到下降方向后, 通过线性搜索计算步长:
于是更新解的形式为
利用 \(b(\mathbf{x},\gamma)\) 拟合伪响应 (pseudoresponses) \(\{-\mathbf{g}_m(\mathbf{x}_i)\}^N_{i=1}\), 这样就可以把难以优化的问题 \(\eqref{loss1}\) 转化为了较容易优化的问题 \(\eqref{loss2}\) 和单参数优化问题. 这样便得到了下面基本的梯度提升 (Gradient Boosting) 算法框架:
- 初始化
- 在每一轮 \(m=1,2,\cdots,M\) 顺次执行以下操作:
- 对 \(i=1,2,\cdots,N\), 计算下降方向
- 用基学习器拟合下降方向 \(\{r_{mi}\}^N_{i=1}\), 得到第 \(m\) 轮基学习器的参数
- 线性搜索计算下降步长
- 更新强学习器\[f_m(\mathbf{x}) = f_{m-1}(\mathbf{x}) + \beta_m b(\mathbf{x},\gamma_m) \]
- 输出强学习器
下面给出一些常用的损失函数以及相应的负梯度:
-
平方损失函数
\[L(y_i, f(\mathbf{x}_i)) = \frac{1}{2}[y_i - f(\mathbf{x}_i)]^2 \]负梯度为
\[-\frac{\partial L(y_i, f(\mathbf{x}_i))}{\partial f(\mathbf{x}_i)} = y_i - f(\mathbf{x}_i) \] -
绝对损失函数
\[L(y_i, f(\mathbf{x}_i)) = |y_i - f(\mathbf{x}_i)| \]负梯度为
\[-\frac{\partial L(y_i, f(\mathbf{x}_i))}{\partial f(\mathbf{x}_i)} = \text{sign} (y_i - f(\mathbf{x}_i)) \] -
Huber 损失函数, 这是平方损失与绝对损失的混合, 对于原理中心的异常点采用绝对损失, 中心附近的采用平方损失, 这个界限一般用分位数 \(\delta = \alpha \text{th-quantile}\{|y_i - f(\mathbf{x}_i)|\}\) 度量.
\[\begin{equation} L(y_i, f(\mathbf{x}_i)) = \left\{ \begin{aligned} &\frac{1}{2}(y_i - f(\mathbf{x}_i))^2, &|y_i - f(\mathbf{x}_i)| \leq \delta \\ &\delta (|y_i - f(\mathbf{x}_i)| - \frac{\delta}{2}), &|y_i - f(\mathbf{x}_i)| > \delta \end{aligned} \right. \end{equation} \]负梯度为
\[\begin{equation} -\frac{\partial L(y_i, f(\mathbf{x}_i))}{\partial f(\mathbf{x}_i)} =\left\{ \begin{aligned} & y_i - f(\mathbf{x}_i), &|y_i - f(\mathbf{x}_i)| \leq \delta \\ & \delta \text{sign} (y_i - f(\mathbf{x}_i)), &|y_i - f(\mathbf{x}_i)| > \delta \end{aligned} \right. \end{equation} \]
上面三种损失函数分别对应三种梯度提升树模型, 在正态误差下 LS_TreeBoost (平方损失) 表现较好; 在异常值较多的情况下 LAD_TreeBoost (绝对损失) 表现较好; M_TreeBoost (Huber 损失) 在这两种情况下都接近最好表现. 因此, 在实际应用中, 如果数据的清洁度不能保证或数据存在较多离群值, 那么 M_TreeBoost 的相对较高的精度, 一致的性能和鲁棒性可能是一个很大的优势.
GBDT 回归算法
在这一节考虑 GBDT 回归树算法, 基学习器为回归决策树. 假设 GBDT 第 \(m\) 轮基学习器是一个有 \(J_m\) 个叶节点的回归树, 将输入空间划分为 \(J_m\) 个互不相交的区域 \(R_m^{1}, R_m^{2}, \cdots, R_m^{J_m}\), 并且在每个区域上确定输出的常量 \(c_m^j\), 那么第 \(m\) 轮基学习器决策树模型可以表示为:
其中, 参数 \(\Theta = \{ (R^1_m, c^1_m), (R^2_m, c^2_m),\cdots, (R^{J_m}_m, c^{J_m}_m) \}\) 表示树的区域划分和各区域上的常数输出值, \(J_m\) 是回归树的复杂度即叶节点个数. 于是上面梯度提升框架中用基学习器拟合下降方向就相当于用回归树来拟合下降方向 \(\{r_{mi}\}^N_{i=1}\), 得到对应的 \(J_m\) 个区域 \(R_m^{1}, R_m^{2}, \cdots, R_m^{J_m}\), 以及在每个区域上确定输出的常量 \(c_m^j\). 与一般的决策树算法相同, 根据 MSE 准则寻找最优切分变量和切分点来划分区域. 而对于每个区域上系数的具体形式, CART 回归树采用 MSE 最小的准则来求解每个区域上的最优输出值, 即在任意区域 \(R^j_m\) 中最小化
易知最优的 \(c^j_m\) 是区域 \(R^j_m\) 上所有特征 \(\mathbf{x}_i\) 对应伪标签 \(r_{mi}\) 的均值, 即
将上述内容代入梯度提升算法框架中, 得到更新形式如下
其中 \(\gamma^j_m = \beta_m c^j_m\), 线性搜索的目标变为
实际上, 回归树产生的区域具有不相交的性质, 上面可直接简化为
事实上这里的 \(\gamma^j_m\) 可以视为当前 \(m\) 轮各叶节点的取值. 由此就得到了 GBDT 回归树的算法框架, 这个算法也称为多重加性回归树 (multiple additive regression trees, MART).
下面总结回归问题的梯度提升算法, 输入训练数据集 \(T = \{ (\mathbf{x}_1, y_1), (\mathbf{x}_2, y_2), \cdots, (\mathbf{x}_N, y_N) \}\), \(\mathbf{x}_i \in \mathcal{X} \subset \mathbb{R}^n\), \(\mathcal{X}\) 为输入空间, \(y_i \in \mathcal{Y} \subset \mathbb{R}\), \(\mathcal{Y}\) 为输出空间, 指定损失函数 \(L(y, f(\mathbf{x}))\). 输出强学习器 \(f(\mathbf{x})\).
- 初始化提升树模型, 估计使损失函数极小化的常数值, 是只有一个根节点的树,
- 在每一轮 \(m=1,2,\cdots,M\) 顺次执行以下操作:
- 对 \(i=1,2,\cdots,N\), 计算
- 对 \(\{r_{mi}\}^N_{i=1}\) 拟合一个 CART 回归树, 得到第 \(m\) 个回归树, 其对应的节点划分区域为 \(R_{mj}\), \(j=1,2,\cdots,J_m\).
- 对每个叶节点划分区域 \(j=1,2,\cdots,J_m\) 计算最佳拟合值
- 更新强学习器 (提升树模型)
- 得到强学习器 (回归提升树模型)
GBDT 分类算法
现在叙述 GBDT 分类算法, GBDT 的分类算法从思想上和 GBDT 的回归算法没有区别, 但是由于样本输出不是连续, 而是离散的类别, 导致无法直接从输出类别去拟合类别输出的误差. 为了解决这个问题, 主要有两个方法, 一个是用指数损失函数, 此时问题可直接转化为之前叙述的 Adaboost 算法解决. 另一种方法是用类似于逻辑回归的对数似然损失函数的方法, 也就是使用类别的预测概率值和真实概率值的差来拟合损失, 对于对数似然损失函数, 以下分别叙述二元分类算法和多元分类算法.
二元 GBDT 分类算法
对于二元 GBDT 分类算法, 对数似然损失函数定义为:
其中, \(y \in \{ -1, +1\}\), 此时的负梯度为:
对于生成的决策树, 每个叶节点划分区域 \(j=1,2,\cdots,J_m\) 的最佳拟合值为
由于上式较难直接求解, 一般使用近似值代替
除了负梯度计算和叶子节点的最佳负梯度拟合的线性搜索, 二元 GBDT 分类和 GBDT 回归算法过程相同.
多元 GBDT 分类算法
多元分类问题是二元分类问题的扩展, 需要考虑 softmax 模型, 即第 \(k\) 类的概率 \(P(y=k|\mathbf{x})\) 可表示为:
其中 \(f_{k}(\mathbf{x})\) 是 \(K\) 个不同的梯度提升树模型, \(f(\mathbf{x}) = [f_{1}(\mathbf{x}),\cdots,f_{K}(\mathbf{x})]\), 多元分类 GBDT 实际上是在每一轮训练了\(K\) 个回归树去拟合 softmax 模型每个维度的负梯度. 其中模型的损失函数定义如下, 也就是交叉熵损失函数:
这里的 \(y = [y_1,y_2,\cdots,y_K]\) 是样本标签在 \(K\) 个类别上作 one-hot 编码之后的取值, 只有一维为 \(1\), 其余为 \(0\). 可以计算出第 \(m\) 轮的第 \(i\) 个样本 \(\mathbf{x}_i\) 对应类别 \(k\) (即该轮第 \(k\) 个决策树所对应的) 的负梯度为
这里的负梯度就是样本 \(\mathbf{x}_i\) 对应类别 \(k\) 的真实概率与 \(m-1\) 轮预测概率的差值.
对于生成的 \(K\) 个决策树, 对其中每个叶节点划分区域 \(j=1,2,\cdots,J_{km}\) 的最佳拟合值为
一般采用近似值代替计算:
GBDT 的正则化
为了防止过拟合, 需要对 GBDT 进行正则化, GBDT 的正则化主要有三种方式.
-
第一种是加入和 Adaboost 类似的正则化项 \(\upsilon\), 即步长 (learning rate), 对于前面的弱学习器的迭代:
\[f_{m}(\mathbf{x}) = f_{m-1}(\mathbf{x}) + T(\mathbf{x}; \Theta_m) \]加上正则化项后变为
\[f_{m}(\mathbf{x}) = f_{m-1}(\mathbf{x}) + \upsilon T(\mathbf{x}; \Theta_m) \]其中 \(0 < \upsilon \leq 1\), 对于同样的训练集学习, 较小的 \(\upsilon\) 意味着需要更多的弱学习器的迭代次数, 通常用步长和迭代最大次数一起来决定算法的拟合效果. 经验表明, 相较于 \(\upsilon=1\), 一个小的步长 (\(\upsilon<0.1\)) 可以显著提高模型的泛化能力.
-
第二种正则化方法是通过子采样 (subsample) 的方式. 子采用比例的取值范围为 \((0,1]\), 每一轮迭代, 新的决策树拟合的是原始训练集的一个子集 (注意随机森林使用的是有放回抽样, 当取值为 \(1\) 就是全部训练集), 这个子集是通过对原始训练集采用不放回抽样得到的. 选择较小的子采样比例可以减少方差, 即防止过拟合, 但是会增加样本拟合的偏差, 因此取值不能太低, 推荐在 \([0.5, 0.8]\) 之间.
采用子采样的 GBDT 有时也称作随机梯度提升树 (Stochastic Gradient Boosting Tree, SGBT). 由于使用了子采样, 程序可以通过采样分发到不同的任务去做 boosting 的迭代过程, 最后形成新树, 从而克服弱学习器难以并行学习的弱点. 其另一个好处是, 未被采样的另一部分子集可以用来计算包外估计误差, 因此可以避免额外给出一个独立的验证集.
-
第三种方法是直接对弱学习器即 CART 决策树进行正则化剪枝.

浙公网安备 33010602011771号