net.zero_grad() 与 optim.zero_grad() pytorch

Sch*_*h21 9 reinforcement-learning pytorch

在这里,他们提到需要optim.zero_grad()在训练时将参数梯度归零。我的问题是:我也可以这样做吗net.zero_grad(),会产生同样的效果吗?还是有必要做 optim.zero_grad()。此外,如果我两者都做会发生什么?如果我什么都不做,那么梯度就会累积,但这究竟是什么意思?他们会被添加吗?换句话说,doingoptim.zero_grad()net.zero_grad(). 我问是因为在这里,他们使用第 115 行net.zero_grad(),这是我第一次看到,这是强化学习算法的实现,其中必须特别小心梯度,因为有多个网络和梯度,所以我假设他们有理由这样做net.zero_grad()而不是optim.zero_grad()

Mic*_*ngo 15

net.zero_grad()将其所有参数(包括子模块的参数)的梯度设置为零。如果你调用optim.zero_grad()它会做同样的事情,但是对于所有被指定要优化的参数。如果您仅net.parameters()在优化器中使用,例如optim = Adam(net.parameters(), lr=1e-3),则两者是等效的,因为它们包含完全相同的参数。

您可以拥有由同一优化器优化的其他参数,它们不是 的一部分net,在这种情况下,您必须手动将其梯度设置为零并因此跟踪所有参数,或者您可以简单地调用optim.zero_grad()以确保所有正在优化的参数的梯度都设置为零。

此外,如果我两者都做会发生什么?

没什么,梯度将再次设置为零,但由于它们已经为零,因此绝对没有区别。

如果我什么都不做,那么梯度就会累积,但这究竟是什么意思?他们会被添加吗?

是的,它们正在被添加到现有的渐变中。在向后传递中,计算每个参数的梯度,然后将梯度添加到参数的梯度 ( param.grad) 中。这允许您有多个反向传递,影响相同的参数,如果梯度被覆盖而不是被添加,这是不可能的。

例如,如果您需要更大的批次以提高训练稳定性,但没有足够的内存来增加批次大小,则可以在多个批次上累积梯度。这在 PyTorch 中实现是微不足道的,它本质上是停止optim.zero_grad()和延迟,optim.step()直到您收集到足够的步骤,如HuggingFace - 在更大批量上训练神经网络:1-GPU、多 GPU 和分布式设置的实用技巧中所示

这种灵活性的代价是必须手动将梯度设置为零。坦率地说,即使很多用户不会使用它,尤其是初学者可能会觉得它很混乱,但支付一条线的成本非常低。