为什么我们在 Gradient Boosting 中使用梯度而不是残差?

数据挖掘 机器学习 xgboost 优化 梯度下降
2021-09-30 13:42:50

我发现使用梯度而不是实际残差有两个优点:

1)使用梯度将允许我们插入任何损失函数(不仅仅是 mse),而无需更改我们的基础学习器以使其与损失函数兼容。

2) 它在计算上可能是不可行的(在 MAE 的情况下,我们必须计算每次拆分的中位数)。

但是,我不明白这些要点,即:

1)如果我们只计算残差并让基础学习器拟合这些值,那究竟比计算梯度然后拟合这些值更困难吗?

2) 继上述问题之后,为什么我们需要在 MAE 示例中计算中位数而不是仅仅获得残差?

也许我不了解优化单个损失函数背后的确切机制。如果有人能够准确地证明 MAE 是如何完成的,以及在哪一步中使用残差是不可行的,那将是非常棒的。

2个回答

嗯,我对你的问题有点困惑。

在梯度提升中,我们确实使用了残差。残差是梯度。

你可以查看我的梯度提升的简单实现这就是魔法发生的地方:

def fit(self, X, y):
    self.fs = [self.first_estimator]
    # step 0
    f = self.first_estimator.fit(X, y)
    # step 1
    for m in range(self.M):
        f = self.predict(X)
        # step 2
        U = self.loss(y, f)
        # step 3
        g = clone(self.base_estimator).fit(X, U)
        # step 4
        self.fs.append(g)

你从一个虚拟模型开始 f. 然后你创建一个新模型g 基于现有集成的错误 L(f(x),y). 代码应该非常简单。检查维基百科页面中的算法以获得更正式的演示。


为什么我使用残差和梯度作为可互换的词?

你有离散数学和连续数学。

在神经网络中,我们使用来自连续数学的梯度定义。你有一个损失函数是C1 连续的(意味着损失必须至少可微一次)。

f(x)=limh0f(x+h)f(x)h

在梯度提升中,我们使用离散数学中梯度的定义。它通常被称为有限差分,而不是导数或梯度。

f(x)=f(x+1)f(x)

就个人而言,我认为梯度是用词不当。但这是营销。梯度提升听起来比“差异提升”或“残差提升”更数学和复杂。

顺便说一句,当梯度提升被发明时,提升这个术语就已经存在了。它用于 AdaBoost,它根据损失改变观察的权重,而不是在残差中进行训练。AdaBoost 仅适用于模型(每个模型都必须犯错误),而梯度提升可以重新采样并适用于模型。


梯度提升的重点

梯度提升(离散优化)和神经网络(连续优化)之间的一个重要区别是梯度提升允许您使用导数为常数的函数。

在梯度提升中,您可以使用“奇怪”的函数,如 MAE 或Pinball 函数在我的代码中,您可以看到您可以在 MSE、MAE 和分位数(即弹球损失)之间进行选择。后两者不适用于神经网络。

pinball 损失用于分位数预测,如能源系统中的风预测。这就是为什么在这些系统中大量使用梯度提升的原因。

小点:很多人认为 MAE 和 Pinball 函数对神经网络效果不好的原因是因为它们不是连续的。虽然这是真的,但它们不是连续的,当y=y^,很容易解决这个问题。这不是这些损失导致结果如此糟糕的原因。它们不能很好地工作的原因是因为优化步骤使用梯度(在梯度下降中),并且梯度对于整个函数是恒定的L(y,y^)=1 或者 L(y,y^)=1,因此梯度的大小始终为 1。优化将仅取决于您使用的学习率启发式算法,这通常不会很好地工作。

我知道这是一个老问题,但我花了一段时间才弄清楚

梯度提升算法每次迭代的目标是找到一个基学习器,它对损失函数 L 的改进最大,我们可以这样写

在此处输入图像描述

这里 L() 是损失函数, yi 是目标, y^i(t1) 是上一次迭代的估计, ν 是学习率和 ft(xi) 是基础学习者。

Gradient Boosting 是对上述方程的一阶近似,我们采用一阶级数展开,结果是;找到基础学习者ft 最小化 L(gi,ft(xi)) 在哪里 gi 是梯度 L(yi,y^i)关于y^在当前迭代中t. 换句话说,将每个基础学习器拟合到上一次迭代的损失函数的 -ve 梯度。

因此,对于一般的损失函数,梯度提升要求我们在每一步拟合梯度,而对于均方损失,梯度恰好是残差,所以虽然看起来有点直观,但将梯度提升视为拟合残差(甚至是梯度经常被命名的伪残差),它实际上是函数空间中的梯度下降。