这里他们提到在训练参数梯度为零时需要包括optim.zero_grad()。我的问题是:我可以做同样的net.zero_grad(),这会有同样的效果吗?还是有必要做optim.zero_grad()。而且,如果我同时做这两件事会发生什么呢?如果我什么也不做,那么梯度就会累积起来,但这到底意味着什么呢?他们被加进去了吗?换句话说,做optim.zero_grad()和net.zero_grad()有什么区别。我问是因为这里,第115行他们使用net.zero_grad(),这是我第一次看到,这是一种强化学习算法的实现,在这种算法中,人们必须特别小心梯度,因为有多个网络和梯度,所以我想他们有理由做net.zero_grad()而不是optim.zero_grad()。
发布于 2020-05-19 22:05:37
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和分布式设置的实用提示所示。
这种灵活性的代价是必须手动将梯度设置为零。坦率地说,一条线是一个非常小的成本,即使许多用户不会使用它,特别是初学者可能会感到困惑。
https://stackoverflow.com/questions/61898668
复制相似问题