为什么我们需要在PyTorch中明确归零渐变?为什么在调用loss.backward()
时不能将渐变归零?通过在图表上保持渐变并要求用户明确归零渐变来实现什么样的场景?
我们明确需要调用zero_grad()
,因为在loss.backward()
之后(当计算梯度时),我们需要使用optimizer.step()
来进行梯度下降。更具体地说,梯度不会自动归零,因为这两个操作loss.backward()
和optimizer.step()
是分开的,而optimizer.step()
需要刚刚计算出的梯度。
另外,有时候,我们需要在一些批次之间积累梯度;要做到这一点,我们可以简单地多次调用backward
并优化一次。
我有一个PyTorch当前设置的用例。
如果正在使用在每个步骤进行预测的递归神经网络(RNN),人们可能希望有一个超参数,允许人们及时积累渐变。不是每次都将梯度归零,步骤允许人们以有趣和新颖的方式使用反向传播时间(BPTT)。
如果您想了解有关BPTT或RNN的更多信息,请参阅文章Recurrent Neural Networks Tutorial, Part 3 – Backpropagation Through Time and Vanishing Gradients或The Unreasonable Effectiveness of Recurrent Neural Networks。
在调用.step()
之前保留梯度非常有用,以防您想要在多个批次中累积渐变(正如其他人提到的那样)。
如果你想为SGD实现动量,它在调用.step()
之后也很有用,其他各种方法可能依赖于前一个更新渐变的值。
因为,loss.backward()
没有任何指定方式。
torch.autograd.backward(tensors, grad_tensors=None, retain_graph=None, create_graph=False, grad_variables=None)
从您可以指定的所有选项中,无法手动将渐变归零。
有一些讨论关于每次使用zero_grad()
做backward()
和保持毕业生preserve_grads=True
,但这从未实现。