Tensor和stack在求导时的区别

今天遇到了一个简单的需求,神经网络预测出一个角度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唬住了,所以研究了好久。

Built with Hugo
Theme Stack designed by Jimmy