为什么我在 Pytorch 的加载模型中得到 NONE 参数梯度,即使在 backword 之后?

Why do I get NONE gradient of parameters in a loaded model in Pytorch, even after backword?

我有一个被

保存的预训练模型
torch.save(net, 'lenet5_mnist_model')

现在我正在加载它并尝试像这样计算渔民信息矩阵:

precision_matrices = {}
batch_size = 32
my_model = torch.load('lenet5_mnist_model')
my_model.eval()              #  I tried to comment this off, but still no luck
for n, p in deepcopy({n: p for n, p in my_model.named_parameters()}).items()
   p = torch.tensor(p, requires_grad = True)
   p.data.zero_()
   precision_matrices[n] = variable(p.data)
for idx in range(int(images.shape[0]/batch_size)):
   x = images[idx*batch_size : (idx+1)*batch_size]
   my_model.zero_grad()
   x = Variable(x.cuda(), requires_grad = True)
   output = my_model(x).view(1,-1)
   label = output.max(1)[1].view(-1)
   loss = F.nll_loss(F.log_softmax(output, dim=1), label)
   loss = Variable(loss, requires_grad = True)
   loss.backward()
   for n, p in my_model.named_parameters():
       precision_matrices[n].data += p.grad.data**2

最后,上面的代码会在最后一行崩溃,因为p.grad是NoneType。所以错误是:

AttributeError: 'NoneType' 对象没有属性 'data'。

有人可以提供一些指导,说明是什么导致了参数的 NoneType 渐变吗?我应该如何解决这个问题?

你的损失不会通过模型反向传播梯度,因为你正在创建一个具有实际损失值的新损失张量,它是计算图的叶子,这意味着没有历史可以反向传播.

loss.backward() 需要在 loss = F.nll_loss(F.log_softmax(output, dim=1), label) 的输出上调用。

我假设您认为需要使用 requires_grad=True 创建张量才能计算梯度。事实并非如此。使用 requires_grad=True 创建的张量是计算图的叶子(它们开始计算图),并且跟踪对作为图的一部分的任何张量执行的每个操作,以便梯度可以通过中间结果流向叶子。只有需要优化的张量(即可学习参数)应该手动设置 requires_grad=True(模型的参数会自动设置),其他关于梯度的一切都是推断出来的。 xloss 都不是可学习的参数。

这种混淆大概是由于使用 Variable 引起的。它在 2 年前发布的 PyTorch 0.4.0 中被弃用,它的所有功能都已合并到张量中。请不要使用 Variable.

x = images[idx*batch_size : (idx+1)*batch_size]
my_model.zero_grad()
x = x.cuda()
output = my_model(x).view(1,-1)
label = output.max(1)[1].view(-1)
loss = F.nll_loss(F.log_softmax(output, dim=1), label)
loss.backward()