我很困惑…
我的模型输出是:tensor([[0.0000,0.1537],...],grad_fn=<ReluBackward0>)
如果我使用print(output.grad)
,它会显示None
,即使在执行了loss.backward()
计算梯度后,结果还是None
…
即使添加了with torch.set_grad_enabled(True):
,结果依然相同。
我已经尝试了多种模型变体,结果始终如一。
我的模型之前表现得很好,似乎没有问题,现在看到这个情况,我开始怀疑是否存在我之前未察觉到的重大缺陷。但我的模型确实是在学习,性能也在提升,所以我觉得应该没有问题吧?
为什么我得到的是None而不是实际的值呢?
回答:
你得到None
是因为梯度只存储在计算图中叶子张量的.grad
属性上。叶子张量是指在计算图中没有父节点的张量。
你可以通过is_leaf
检查一个张量是否为叶子张量:
>>> x = torch.FloatTensor([1,2,3])>>> x.requires_grad = True>>> x.sum().backward() # 反向传播>>> x.is_leafTrue>>> x.gradtensor([1., 1., 1.])
你打印的张量显示grad_fn=<ReluBackward0>
,表明它是ReLU层的输出,因此不是叶子张量。
下面是一个非叶子张量的例子:
>>> x = torch.FloatTensor([1,2,3])>>> x.requires_grad=True>>> z = x.sum()>>> z.backward()>>> z.is_leafFalse>>> z.gradNone
请注意,z
将显示为tensor(6., grad_fn=<SumBackward0>)
。
实际上访问.grad
会触发警告:
UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won’t be populated during autograd.backward(). If you indeed want the gradient for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead.
如果想要访问非叶子张量的梯度,按照警告信息操作:
>>> z.retain_grad()>>> z = x.sum()>>> z.retain_grad()>>> z.backward()>>> z.is_leafFalse>>> z.gradtensor(1.)