火炬逆向不return张量
Torch backward do not return a tensor
为了设置问题,我将矩阵 X 作为输入,将矩阵 Y 作为输出,我们通过矩阵与 W 的乘法得到 Y,我通过指数进行乘法。根据我从 torch.backward() 中了解到的带有梯度参数的公式应该如下
然而 dy_over_dx 作为雅可比矩阵应该是一个大小为 的张量(我的意思不是通常的 n x n 维矩阵)。
X = torch.tensor( [[2.,1.,-3], [-3,4,2]], requires_grad=True)
W = torch.tensor( [ [3.,2.,1.,-1] , [2,1,3,2 ] , [3,2,1,-2] ], requires_grad=True)
Y = torch.exp(torch.matmul(X, W))
Y.retain_grad()
print(Y)
dL_over_dy = torch.tensor( [[2,3,-3,9],[-8,1,4,6]])
print(dL_over_dy, dL_over_dy.shape)
Y.backward(dL_over_dy)
print(X.grad)
tensor([[3.6788e-01, 3.6788e-01, 7.3891e+00, 4.0343e+02],
[1.4841e+02, 7.3891e+00, 5.9874e+04, 1.0966e+03]],
grad_fn=<ExpBackward>)
tensor([[ 2, 3, -3, 9],
[-8, 1, 4, 6]]) torch.Size([2, 4])
tensor([[ -3648.6118, 7197.7920, -7279.4707],
[229369.6250, 729282.0625, 222789.8281]])
接下来,如果我查看我认为是 dy_over_dx 的 Y 的梯度,我在这里有什么不明白的?
print(Y.grad)
tensor([[ 2., 3., -3., 9.],
[-8., 1., 4., 6.]])
您在这里看到的是 Y.grad
,即 dL/dY
即 none 而不是 dL_over_dy
。
为了帮助澄清,让 Z = X @ Y
(@
等同于 matmul
)和 Y = exp(Z)
。然后我们有了链式规则:
Y.grad = dL/dY
Z.grad = dL/dZ = dL/dY . dY/dZ
,其中 dY/dZ = exp(Z) = Y
X.grad = dL/dX = dL/dZ . dZ/dX
,其中 dZ/dX = d(X@W)/dX = W.T
实现如下:
X = torch.tensor([[ 2., 1., -3],
[ -3, 4., 2.]], requires_grad=True)
W = torch.tensor([[ 3., 2., 1., -1],
[ 2., 1., 3., 2.],
[ 3., 2., 1., -2]], requires_grad=True)
Z = torch.matmul(X, W)
Z.retain_grad()
Y = torch.exp(Z)
dL_over_dy = torch.tensor([[ 2., 3., -3, 9.],
[ -8, 1., 4., 6.]])
Y.backward(dL_over_dy)
然后我们有
>>> dL_over_Z = dL_over_dy*Y
tensor([[ 7.3576e-01, 1.1036e+00, -2.2167e+01, 3.6309e+03],
[-1.1873e+03, 7.3891e+00, 2.3950e+05, 6.5798e+03]],
grad_fn=<MulBackward0>)
>>> dL_over_X = dL_over_Z @ W.T
tensor([[ -3648.6118, 7197.7920, -7279.4707],
[229369.6250, 729282.0625, 222789.8281]], grad_fn=<MmBackward0>)
为了设置问题,我将矩阵 X 作为输入,将矩阵 Y 作为输出,我们通过矩阵与 W 的乘法得到 Y,我通过指数进行乘法。根据我从 torch.backward() 中了解到的带有梯度参数的公式应该如下
然而 dy_over_dx 作为雅可比矩阵应该是一个大小为
X = torch.tensor( [[2.,1.,-3], [-3,4,2]], requires_grad=True)
W = torch.tensor( [ [3.,2.,1.,-1] , [2,1,3,2 ] , [3,2,1,-2] ], requires_grad=True)
Y = torch.exp(torch.matmul(X, W))
Y.retain_grad()
print(Y)
dL_over_dy = torch.tensor( [[2,3,-3,9],[-8,1,4,6]])
print(dL_over_dy, dL_over_dy.shape)
Y.backward(dL_over_dy)
print(X.grad)
tensor([[3.6788e-01, 3.6788e-01, 7.3891e+00, 4.0343e+02],
[1.4841e+02, 7.3891e+00, 5.9874e+04, 1.0966e+03]],
grad_fn=<ExpBackward>)
tensor([[ 2, 3, -3, 9],
[-8, 1, 4, 6]]) torch.Size([2, 4])
tensor([[ -3648.6118, 7197.7920, -7279.4707],
[229369.6250, 729282.0625, 222789.8281]])
接下来,如果我查看我认为是 dy_over_dx 的 Y 的梯度,我在这里有什么不明白的?
print(Y.grad)
tensor([[ 2., 3., -3., 9.],
[-8., 1., 4., 6.]])
您在这里看到的是 Y.grad
,即 dL/dY
即 none 而不是 dL_over_dy
。
为了帮助澄清,让 Z = X @ Y
(@
等同于 matmul
)和 Y = exp(Z)
。然后我们有了链式规则:
Y.grad = dL/dY
Z.grad = dL/dZ = dL/dY . dY/dZ
,其中dY/dZ = exp(Z) = Y
X.grad = dL/dX = dL/dZ . dZ/dX
,其中dZ/dX = d(X@W)/dX = W.T
实现如下:
X = torch.tensor([[ 2., 1., -3],
[ -3, 4., 2.]], requires_grad=True)
W = torch.tensor([[ 3., 2., 1., -1],
[ 2., 1., 3., 2.],
[ 3., 2., 1., -2]], requires_grad=True)
Z = torch.matmul(X, W)
Z.retain_grad()
Y = torch.exp(Z)
dL_over_dy = torch.tensor([[ 2., 3., -3, 9.],
[ -8, 1., 4., 6.]])
Y.backward(dL_over_dy)
然后我们有
>>> dL_over_Z = dL_over_dy*Y
tensor([[ 7.3576e-01, 1.1036e+00, -2.2167e+01, 3.6309e+03],
[-1.1873e+03, 7.3891e+00, 2.3950e+05, 6.5798e+03]],
grad_fn=<MulBackward0>)
>>> dL_over_X = dL_over_Z @ W.T
tensor([[ -3648.6118, 7197.7920, -7279.4707],
[229369.6250, 729282.0625, 222789.8281]], grad_fn=<MmBackward0>)