我在使用PyTorch进行梯度计算时遇到了麻烦。
我具有RNN的上一个时间步T
的输出和隐藏状态。
我想克隆我的隐藏状态并在反向传播后计算其grad,但它不起作用。
阅读pytorch how to compute grad after clone a tensor后,我使用retain_grad()
并没有成功。
这是我的代码
hidden_copy = hidden.clone()
hidden.retain_grad()
hidden_copy.retain_grad()
outputs_T = outputs[T]
targets_T = targets[T]
loss_T = loss(outputs_T,targets_T)
loss_T.backward()
print(hidden.grad)
print(hidden_copy.grad)
hidden_grad
给出一个数组,而hidden_copy.grad
给出None
。
为什么hidden_copy.grad
给None
?有什么方法可以计算出克隆张量的梯度吗?
答案 0 :(得分:0)
基于注释,问题在于hidden_copy
在反向传递期间从未访问过。
执行向后pytorch时,计算图形将从loss_T
开始向后进行,并向所有叶节点进行向后工作。它仅访问用于计算loss_T
的张量。如果张量不是该向后路径的一部分,则将不会访问它,并且它的grad
成员也不会被更新。基本上,通过创建张量的副本然后不使用它来计算loss_T
,这将在计算图中导致“死角”。
为说明起见,请看一下该图,它表示计算图的简化视图。图中的每个节点都是张量,边缘指向直接后代。
请注意,如果我们遵循从loss_T
回到叶子的路径,那么我们将永远不会访问hidden_conv
。请注意,叶子是没有后代的张量,在这种情况下,input
是唯一的叶子。
这是一个非常简化的计算图,用于演示一个点。当然,实际上input
和hidden
之间以及hidden
和output_T
之间可能还有更多的节点,以及其他叶子张量,因为层的权重几乎可以肯定是叶子