为什么我们需要显式调用zero_grad()?

Was*_*mad 45 neural-network gradient-descent deep-learning pytorch

为什么我们需要在PyTorch中明确归零渐变?loss.backward()调用时为什么渐变不能归零?通过在图表上保持渐变并要求用户明确归零渐变来实现什么样的场景?

dan*_*che 48

我们明确需要调用zero_grad()因为,在loss.backward()(计算渐变之后)之后,我们需要使用optimizer.step()梯度下降.更具体地说,梯度不会自动归零,因为这两个操作,loss.backward()以及optimizer.step()被分离,并optimizer.step()要求只计算梯度.

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


小智 5

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

如果正在使用在每个步骤进行预测的递归神经网络(RNN),人们可能希望有一个超参数,允许人们及时积累渐变.不是每次都将梯度归零,步骤允许人们以有趣和新颖的方式使用反向传播时间(BPTT).

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

  • 这个答案需要更清楚。也许一个例子会有所帮助。 (2认同)

pro*_*sti 5

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()
Run Code Online (Sandbox Code Playgroud)

如果我们不清除 之后的梯度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.])
Run Code Online (Sandbox Code Playgroud)

loss.backward() 没有任何方式指定这一点。

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

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

w.grad.zero_()
Run Code Online (Sandbox Code Playgroud)

有一些关于zero_grad()每次使用backward()(显然是以前的渐变)和保持 grads 的讨论preserve_grads=True,但这从未实现。