Lec2.4 Softmax Regression(3)

The gradient of the softmax objective

因为我们如何计算我们真正想要的东西?实际上,我们想要这个东西关于θ\theta的梯度。

我们如何计算它因为我们想要相对于内部的梯度,你可以使用链规则, 但是这里的维度很难处理。而且这是你能想象到的最简单的东西,对吧?这是一个线性的假设函数,但这个术语是一个矩阵,这个术语是一个向量,所以我们希望用矩阵相对于向量求导。这就像一些奇怪的张量一样,事实证明,这很快就会变得非常麻烦。因此,我们需要一些更强大或更具有严谨性的方法。

  • 我们可以先做正确的事情。要清楚,正确的事情是,你可以定义梯度的推广,例如雅可比矩阵,实际上是导数,相对于向量的向量输出,或者所有部分导数的矩阵。但是当你有矩阵时,你不得不使用像Kronecker积和向量化这样的东西。但是你可以使用矩阵微分计算来形式化所有这些内容。因此,确实有一些方法可以正式处理您想要计算的每一个导数,或每个梯度,偏导数和雅可比矩阵在此处。 你也可以逐项使用术语,但那甚至更糟。你可以使用矩阵微分计算来处理这一切。虽然我们并不会这样做。我们要做的很不好,不严谨,但每个人实际上都在做。

  • 如果您以前没有看过这个,这将成为你的启示,如果你以前做过这个梯度的方式,并且从未意识到人们实际上所做的事情,因此我正在揭露这个大秘密。但它甚至不是一个有用的秘密,因为这是我们如何做这些事情的方法。好的,现在计算多元化雅可比矩阵,梯度,导数等的方法不用了。

    1. 我们就是假装一切都是标量,应用正常的链规则,

    2. 也许转置你的输出,使输出的大小正常。

我真的想强调这种恐怖表情符号在这里,你应该对此感到恐惧,所以这实际上是实践中所做的,有点可怕,但这是人们真正做的事情。你会很快习惯它。我要说的是,如果你这样做了,请务必检查你的答案和数字检查你的答案。因为这种方法容易出错。但这确实是我们想要计算令人不快的梯度或高维导数等时所做的,它并不总是有效,但它工作得非常出奇地多。

因此,至少先尝试这个方法。好的。那么这究竟是如何运作的呢?


实际上是我们想要计算的是交叉熵损失关于θ\theta梯度,

但是,假设所有东西都是标量,那么我可以求的就是损失函数关于θ\theta的导数,

θlce(θTx,y)\frac{\partial}{\partial \theta} l_{ce}(\theta^Tx,y)

我仍然会在此使用偏导数符号,即使此时应该只使用普通的d符号,但我将使用偏导数符号来提醒自己我正在严重作弊。但是我们还是可以这样,假装所有这些都是标量值,

然后从那里开始,现在我们可以应用正常的规则,如果我们正在计算这个导数,现在我们可以应用正常的链式法则。

在求导之前,需要注意一点

  • θ\theta视为标量, 那么θT\theta^T便等于θ\theta。在进行如下求导的时候

    θTθ=1\frac{\partial \theta^T}{\partial \theta}=1

    这和对矩阵A的转置关于A求导等于单位矩阵,即

    (AT)A=I\frac{\partial (A^T)}{\partial A} = I

    是一致的。

开始计算

θlce(θTx,y)=lce(θTx,y)θTxθTxθ\frac{\partial}{\partial \theta} l_{ce}(\theta^Tx,y)=\frac{\partial l_{ce}(\theta^Tx,y)}{\partial \theta^Tx } \frac{\partial \theta^Tx}{\partial \theta}

根据前面的幻灯片

hlce(h,y)=zey\nabla_{h} l_{ce}(h,y)=\bold z- \bold e_y

则有

θlce(θTx,y)=(zey)x\frac{\partial}{\partial \theta} l_{ce}(\theta^Tx,y)=(z-e_y)x
  • z=exp(xi)j=1kexp(xj)z= \frac{\exp(x_i)}{\sum_{j=1}^k \exp(x_j)}

好的,现在我们差不多完成了,现在我们只需要谈论一下矩阵的大小。

好的,这里的zzeye_y都是k维向量,所以这是一个k维向量,实际上是一个k x 1维的矩阵,而这个项是x,是一个n x 1的向量,也就是一个n x 1维的矩阵。

而我们想要的梯度是n x k,那么我们如何安排这两个项,使其成为一个n x k维的输出?我们唯一的选择是写成

x(zey)T\bold x(\bold z-\bold e_y)^T

这样就可以得到一个n x k维的矩阵,实际上,这就是我们要求的正确梯度。所以是的,我们用这种非常尴尬的方式进行计算,但我们必须这样做,实际上,在自动微分中,甚至在推导某些操作的梯度时,你也需要这样做。

好的,关于这个有趣的事情是,即使在批处理的情况下也适用。所以我们可以再次滥用符号,我们可以将真正想要的损失函数应用于整个小批量的假设,只是XθX \theta的形式。我们可以以完全相同的方式编写所有内容,所以现在要求批量计算梯度

θlce(Xθ,y)\nabla_{\theta} l_{ce}(X\theta,y)

而且现在X和y是一个矩阵,这是与之前唯一的区别。

当成标量求导计算是这样的

θlce(Xθ,y)=lce(Xθ,y)XθXθθ=(ZIy)X\frac{\partial}{\partial \theta} l_{ce}(X\theta,y)=\frac{\partial l_{ce}(X\theta,y)}{\partial X\theta } \frac{\partial X\theta}{\partial \theta}=(Z-I_y)X

这里的X应该是m×n, Z我们如何获得最终的乘积呢?依然是考虑大小

  • 那么为什么可以直接θlce(Xθ,y)\nabla_{\theta} l_{ce}(X\theta,y)来梯度下降进行优化,而并不需要计算损失的平均值?

    主要原因在于,梯度下降等优化算法的基本思想是通过迭代更新参数来最小化损失函数。在每个迭代步骤中,我们计算损失函数对于当前参数的梯度向量,并使用它来更新参数。因此,我们可以直接使用每个样本的梯度向量来更新参数,而不需要显式地计算整个数据集的平均损失

这就是我们想要的实际梯度。然后你可能会问,为什么这里有转置,为什么这些转置与这一个相反?记住必须根据设置这些矩阵的方式对它们进行转置。这个东西就是我们要的最终表达式。这实际上相当混乱,现在这是一个矩阵,这里还有一个矩阵。使用Kronecker积、张量化或向量化等方法正确地处理这个过程很麻烦。但是,一旦你推导出它,你可以在数值上验证这是否正确,并且它确实是正确的梯度。所以我想再次提醒你,我们这样做相当令人尴尬。你最终将不会在本课程中使用此方法,因为当然,本课程将是关于如何构建自动微分工具,从而避免这种情况。但是这就是我们用来做机器学习的方式,这曾经是每个人都会做的技巧,

好了,但现在我们完成了。


因此,尽管我承认这是一个相当复杂的推导,但对于softmax回归,我们所剩下的东西是非常简单的。我真的想强调这种简单性。最终的softmax回归算法是什么样子的

  • 你将你的数据分成批次,你迭代这些大小为B的批次。

  • 因此,你迭代训练集,每个批次只需根据此梯度规则更新参数。虽然你必须计算Z以实现此目的,但这是5、6行Python代码。所有你看到的推导最终转化为一个极其简单明了的算法,可以在几行Python代码中实现,在第一份作业中实际上可以实现。这就是softmax回归算法的全部内容。因此,尽管存在一些不容易的数学推导,但你应该承认这里的推导不完全是微不足道的。即便我们有点欺骗性地进入了推导的难点,但这最终是实际生成算法的一行描述,你可以用几行Python代码再次实现它。如果你在MNIST数据上实现它,你会发现你得到了约小于8%的错误率。这可能比我手工做得更好。接下来我们将采用完全相同的方式做同样的事情。

唯一的区别是我们将使用神经网络,但这意味着使用了一个更加花哨的假设类。我们将使用同样的基本损失函数-交叉熵损失函数。我们将使用相同的优化过程-梯度下降或随机梯度下降。自然而然地,计算梯度有点棘手,但过程是相同的。对于深度学习或者神经网络,唯一的区别就是我们使用了一个更加花哨的非线性假设类,代替softmax回归的线性假设类。这将是下一步。在下一步中,我们还要通过旧的冗长方式来进行讲解。之后,我们将以更好的方式讲解,你可以忘记梯度并让你编写的自动微分工具为你完成所有这些数学运算。

Last updated