为什么f(x)关于'x'的导数是'x'而不是pytorch中的1?

Why is the derivative of f(x) with respect to 'x' 'x' and not 1 in pytorch?

我试图完全理解 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的行为?

与同事讨论后,他发现'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。

首先,给定z = torch.linspace(-1, 1, steps=5, requires_grad=True)y = z,函数是向量值函数,所以yw.r.tz的导数并不像 1 那样简单,而是一个雅可比矩阵。实际上在你的情况下 z = [z1, z2, z3, z4, z5]T ,大写 T 意味着 z 是一个行向量。这是官方文档所说的:

其次,请注意官方文档说:现在在这种情况下 y 不再是标量。 torch.autograd 无法直接计算完整的 Jacobian,但如果我们只想要向量-Jacobian 乘积,只需将向量作为参数传递给 backward link。在那种情况下 x.grad 不是实际的梯度值(矩阵)而是 vector-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 教程比较简短,对于初学者来说实际上很难理解。