为什么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
,函数是向量值函数,所以y
w.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 教程比较简短,对于初学者来说实际上很难理解。
我试图完全理解 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
,函数是向量值函数,所以y
w.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 教程比较简短,对于初学者来说实际上很难理解。