为什么在PyTorch中f(x)关于变量'x'的导数是'x'而不是1?

4

我正试图全面理解PyTorch的自动求导(autograd),在这个过程中我遇到了以下问题:假设函数f(x)=x,根据基础数学知识,我们知道f'(x)=1,但是当我在PyTorch中运用该函数时,得到的结果却是f'(x) = x。

z = torch.linspace(-1, 1, steps=5, requires_grad=True)
y = z
y.backward(z)
print("Z tensor is: {} \n Gradient of y with respect to z is: {}".format(z, z.grad))

我希望得到一个大小为5的张量,其中所有元素都是1,但实际上我得到了:
Z tensor is: tensor([-1.0000, -0.5000,  0.0000,  0.5000,  1.0000], requires_grad=True) 
 Gradient of y with respect to z is: tensor([-1.0000, -0.5000,  0.0000,  0.5000,  1.0000])

为什么PyTorch表现出这种行为?
2个回答

2
首先,假设有z = torch.linspace(-1,1,steps = 5,requires_grad = True)y = z ,该函数是一个矢量值函数,因此y相对于z的导数不像1那么简单,而是一个雅各比矩阵。实际上,在您的情况下,z = [z1,z2,z3,z4,z5]T,其中大写字母T表示z是行向量。这是官方文档的说明:

enter image description here

其次,注意官方文档中的说法:现在,在这种情况下,y不再是一个标量。torch.autograd无法直接计算完整的Jacobian矩阵,但是如果我们只需要向量-Jacobian乘积,只需将向量作为参数传递给backward函数link即可。在这种情况下,x.grad不是实际的梯度值(矩阵),而是向量-Jacobian乘积

编辑: 如果输出的y是标量,则x.grad是实际的梯度值。 请参见此处的示例:

z = torch.linspace(-1, 1, steps=5, requires_grad=True)
y = torch.sum(z)
y.backward()
z.grad 

这将输出:
tensor([1., 1., 1., 1., 1.])

如您所见,这是梯度。请注意,唯一的区别在于,在此示例中,y 是标量值,而在您的示例中是矢量值。grad 仅适用于标量输出,并且可以隐式创建

您可能会想知道,如果梯度不是一个常量,例如与输入 z 相关,则会发生什么。

z = torch.linspace(-1, 1, steps=5, requires_grad=True)
y = torch.sum(torch.pow(z,2))
y.backward()
z.grad

输出结果为:
tensor([-2., -1.,  0.,  1.,  2.])

它与之相同。
z = torch.linspace(-1, 1, steps=5, requires_grad=True)
y = torch.sum(torch.pow(z,2))
y.backward(torch.tensor(1.))
z.grad

“blitz教程有点简略,对于初学者来说理解起来相当困难。”

谢谢!我之前已经阅读了文档,但是我并不完全确定它的含义。我认为将矢量雅可比积简称为“grad”有点具有误导性。 - Sergio

0
与同事讨论后,他发现 'backward()' 方法实际上是将在 z 处评估的梯度与 z 本身相乘。这对于神经网络应用程序是有意义的。了解此内容的简短代码片段如下:
z = torch.linspace(1, 5, steps=5, requires_grad=True)
y = torch.pow(z,2)
y.backward(z)
print("Z tensor is: {} \n Gradient of y with respect to z is: {}".format(z, z.grad/z))

输出结果为:

Z tensor is: tensor([1., 2., 3., 4., 5.], requires_grad=True) 
 Gradient of y with respect to z is: tensor([ 2.,  4.,  6.,  8., 10.], grad_fn=<DivBackward0>)

在这种情况下,您可以看到 z.grad 除以 z 是 z 的实际期望梯度,其应该是 2*z。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接