一个梯度反向传播的坑
最近打算在一个已有的loss上进行改进,就是再加一项myloss,然后总的loss设置成tol=loss+myloss,但是发现myloss加了跟没加效果差不多。今天发现其实是myloss那一项没有梯度回传(中间是转成了numpy再转回tensor),相当于网络还是按原来的loss训练的。类似于下面这个例子:
import torch
x = torch.tensor([1.0,2.0,3.0], requires_grad=True)
k = x.detach().numpy()
y = k * 2
myloss = torch.tensor(y.mean(),requires_grad=True)
loss = x.mean()
tol = loss + myloss
tol.backward()
print(x.grad)
输出结果为tensor([0.3333, 0.3333, 0.3333])。分析一下这个算例,tensor([0.3333, 0.3333, 0.3333])恰是原本loss对应的回传梯度,myloss什么作用都没有。进一步地验证:如果没有loss:
import torch
x = torch.tensor([1.0,2.0,3.0], requires_grad=True)
k = x.detach().numpy()
y = k * 2
myloss = torch.tensor(y.mean(),requires_grad=True)
myloss.backward()
print(x.grad)
输出结果None。而如果梯度回传成功,应该输出tensor([0.6667, 0.6667, 0.6667])。确实说明这种方法的话(先转numpy再转tensor),梯度是没法回传的。所以还是得看看能否直接用张量计算的方法来构建myloss。
如果有大佬了解先转numpy再转tensor并且还能正确计算梯度的话,还请评论区留言或者私信我,十分感谢(当时先转numpy是方便调用很多opencv里的函数)。