y.sum().backward()为什么需要.sum()的思考

这是2.5小节的内容,在网上看了一些回答后仍然不是很清楚,深入思考后忽然想明白了,在此记录一下,希望对和我一样有疑惑的人有所帮助 : )

首先,需要明确两点:

  • backward是对标量的操作,没办法对向量进行操作
  • 梯度是偏导数的集合

在清楚这个之后,我们仍然沿用书中的例子。

1. 结果为标量

如果关于向量x的函数为y = torch.dot(x, x) ,也就是点积,这个函数最后得到的是一个标量。如果我们的输入是x = [1, 2, 3],那么y = x1*x1 + x2*x2 + x3*x3 = 1 + 2 + 9 = 12,它的梯度就是[2x1, 2x2, 2x3] = [1, 4, 6]。以上都是我们在高数中学到的,容易理解。

2. 结果为向量

但是当关于x的函数为y = x*x时,就会变的复杂起来。同样的输入x = [1, 2, 3],得到的函数值为y = [x1*x1, x2*x2, x3*x3] = [1, 4, 9],这是一个向量。我们仍然想要求函数的偏导,并且也很清楚对于每一个输入,它的偏导就是[2x1, 2x2, 2x3] = [1, 4, 6],只是backward并不支持对向量的操作。因此,我们进行.sum()操作,将所有的输出加起来,y = x1*x1 + x2*x2 + x3*x3,在求梯度时会发现,虽然相加了起来,但是除了关于x1本身的运算之外,其他的运算会被当做常数项在偏导数中被消去,因此最终就可以得到不同的输入时的偏导,也就是梯度。

3. 理解

上面是一个很简答的例子,在神经网络里有大量的张量运算,要比这个复杂很多。我们进行.sum()的本质在于:偏导是函数的一个性质,对函数成立,我们得到的向量实际上是运算的集合,对向量中的每一个元素而言,都有自己的运算过程,也就是属于自己的函数。将这些结果加起来,再求偏导,等效于对每一个元素对应的函数单独求导。

以上是我并不成熟的思考,没有经过数学上的推理求证,如果有误,十分欢迎各位指出,非常感谢!!让我们一起学习吧!

posted @ 2024-02-28 14:02  ZCry  阅读(114)  评论(0编辑  收藏  举报