今天遇到了一个简单的需求,神经网络预测出一个角度theta,我要用它得到一个旋转矩阵,用于后面的计算。
想着没什么难度,就写了如下代码:
theta = torch.tensor([0.5 * torch.pi/2], requires_grad=True)
R = torch.tensor([[torch.cos(theta), -torch.sin(theta)],
[torch.sin(theta), torch.cos(theta)]],requires_grad=True)
结果发现最后计算梯度的时候theta.grad
始终为None
,但是R是有梯度的,很明显梯度并没有从R传递会theta。后来发现由于R是由torch.tensor
构造的,所以已经被自动求导视作了叶子节点,所以不会进一步回传梯度。解决办法也很简单,把tensor构造该为拼接实现就行了。下面给一个更明显的例子:
import torch
x = torch.randn(1,requires_grad=True)
#错误示范,梯度不会传递回x
y = torch.tensor([x + 2,x * 3],requires_grad=True)
l = y.sum()
l.backward()
print(x.grad) #None
import torch
x = torch.randn(1,requires_grad=True)
z1 = x + 2
z2 = x * 3
y = torch.stack((z1,z2))#这样就可以了
l = y.sum()
l.backward()
print(x.grad) #tensor([4.])
其实不是什么困难的问题,不过因为没有在网上找到类似的问题,又被new bing和claude唬住了,所以研究了好久。