为什么我们需要显式调用zero_grad()? [重复]
deep-learning
gradient-descent
neural-network
pytorch
11
0

为什么我们需要在PyTorch中将梯度显式归零?为什么在loss.backward()时梯度不能归零?通过在图表上保留渐变并要求用户将渐变显式清零,可以提供什么服务?

参考资料:
Stack Overflow
收藏
评论
共 4 个回答
高赞 时间 活跃

PyTorch中有一个循环:

  • 当我们从输入中获得输出或y_hat时,继续前进,
  • 计算损失,其中loss = loss_fn(y_hat, y)
  • 计算梯度时的loss.backward
  • 更新参数时的optimizer.step

或在代码中:

for mb in range(10): # 10 mini batches
    y_pred = model(x)
    loss = loss_fn(y_pred, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

如果我们不清除optimizer.step之后的梯度,这是适当的步骤,或者恰好在下一个backward()梯度累积之前。这是显示累积的示例:

import torch
w = torch.rand(5)
w.requires_grad_()
print(w) 
s = w.sum() 
s.backward()
print(w.grad) # tensor([1., 1., 1., 1., 1.])
s.backward()
print(w.grad) # tensor([2., 2., 2., 2., 2.])
s.backward()
print(w.grad) # tensor([3., 3., 3., 3., 3.])
s.backward()
print(w.grad) # tensor([4., 4., 4., 4., 4.])

loss.backward()没有任何指定方法。

torch.autograd.backward(tensors, grad_tensors=None, retain_graph=None, create_graph=False, grad_variables=None)

您可以从所有选项中指定无法手动将梯度归零。在前面的迷你示例中是这样的:

w.grad.zero_()

有做一些讨论zero_grad()与每次backward()显然以前的梯度),并保持与毕业生preserve_grads=True ,但从来没有来生活。

收藏
评论

我有一个PyTorch中当前设置的用例。

如果使用的是递归神经网络(RNN),它在每一步都进行预测,那么您可能希望拥有一个超参数,以使人们能够及时累积梯度。并非在每个时间步都将梯度设为零,就可以使人们以有趣且新颖的方式使用时间反向传播(BPTT)。

如果您想了解有关BPTT或RNN的更多信息,请参阅文章递归神经网络教程,第3部分–通过时间和消失梯度进行反向传播递归神经网络的不合理有效性

收藏
评论

如果您想在多个批次中累积渐变(如其他人所提到的),则在调用.step()之前将渐变保留在原位非常有用。

如果要为SGD实现动量,则调用.step() 之后也很有用,并且其他各种方法可能取决于先前更新的梯度值。

收藏
评论

我们明确需要调用zero_grad()因为在loss.backward()之后loss.backward()计算梯度时),我们需要使用optimizer.step()进行梯度下降。更具体地说,梯度不会自动归零,因为loss.backward()optimizer.step()这两个操作是分开的,并且optimizer.step()只需计算梯度即可。

另外,有时我们需要累积一些批次之间的梯度;要做到这一点,我们可以简单地调用backward多次和优化一次。

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号