class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.fc1 = nn.Linear(10,5)
self.fc2 = nn.Linear(5,1)
self.fc1.register_forward_hook(self._forward_hook)
self.fc1.register_backward_hook(self._backward_hook)
def forward(self, inp):
return self.fc2(self.fc1(inp))
def _forward_hook(self, module, input, output):
print(type(input))
print(len(input))
print(type(output))
print(input[0].shape)
print(output.shape)
print()
def _backward_hook(self, module, grad_input, grad_output):
print(type(grad_input))
print(len(grad_input))
print(type(grad_output))
print(len(grad_output))
print(grad_input[0].shape)
print(grad_input[1].shape)
print(grad_output[0].shape)
print()
model = Model()
out = model(torch.tensor(np.arange(10).reshape(1,1,10), dtype=torch.float32))
out.backward()
生成输出
<class 'tuple'>
1
<class 'torch.Tensor'>
torch.Size([1, 1, 10])
torch.Size([1, 1, 5])
<class 'tuple'>
2
<class 'tuple'>
1
torch.Size([1, 1, 5])
torch.Size([5])
torch.Size([1, 1, 5])
您可以参考CNN的示例此处。事实上,这是理解我后面提出问题所必需的。
我有几个问题:
通常我认为
grad_input
(反向传播钩子)应该与output
(前向传播钩子)形状相同,因为在向后传播时,方向是相反的。但CNN示例似乎表明不是这样。我还有点困惑。到底是哪一种情况呢?为什么我的
Linear
层上的grad_input[0]
和grad_output[0]
形状相同?无论问题1的答案如何,它们中至少有一个应该是torch.Size([1, 1, 10])
,对吗?元组
grad_input
的第二个元素是什么?在CNN的情况下,我复制粘贴了示例并使用print(grad_input[1].size())
输出结果为torch.Size([20, 10, 5, 5])
。所以我认为这是权重的梯度。我还运行了print(grad_input[2].size())
,得到的输出是torch.Size([20])
。所以看起来我正在查看偏置的梯度。但是在我的Linear
示例中,grad_input
的长度为2,所以我只能访问到grad_input[1]
,它似乎给出了偏置的梯度。那么权重的梯度在哪里呢?
Conv2d
和`Linear'模块中,向后钩子的行为存在两个明显的矛盾。这让我对这个钩子的预期感到完全困惑。谢谢你的帮助!