net.zero_grad() 与 optim.zero_grad() pytorch
Posted
技术标签:
【中文标题】net.zero_grad() 与 optim.zero_grad() pytorch【英文标题】:net.zero_grad() vs optim.zero_grad() pytorch 【发布时间】:2020-09-05 23:13:35 【问题描述】:Here 他们提到在将参数梯度训练为零时需要包含optim.zero_grad()
。我的问题是:我也可以这样做net.zero_grad()
会产生同样的效果吗?还是有必要做optim.zero_grad()
。此外,如果我两者都做会发生什么?如果我什么都不做,那么梯度会累积,但这到底是什么意思?他们被添加了吗?换句话说,做optim.zero_grad()
和net.zero_grad()
有什么区别。我问是因为here, line 115 他们使用net.zero_grad()
,这是我第一次看到,这是强化学习算法的一种实现,因为有多个网络和梯度,所以必须特别小心梯度,所以我想他们有理由这样做net.zero_grad()
,而不是optim.zero_grad()
。
【问题讨论】:
【参考方案1】: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 - Training Neural Nets on Larger Batches: Practical Tips for 1-GPU, Multi-GPU & Distributed setups 所示。
这种灵活性的代价是必须手动将渐变设置为零。坦率地说,一条线路的支付成本非常低,尽管许多用户不会使用它,尤其是初学者可能会感到困惑。
【讨论】:
以上是关于net.zero_grad() 与 optim.zero_grad() pytorch的主要内容,如果未能解决你的问题,请参考以下文章