第一次和第三次尝试完全相同且正确,而第二次尝试完全错误。
原因是,在 Pytorch 中,低层梯度不会被后续的backward() 调用“覆盖”,而是累加或求和。这使得第一种方法和第三种方法相同,但如果您有低内存 GPU/RAM,第一种方法可能更可取,因为立即调用 backward() + step() 的批量大小为 1024 与具有大小为 128 和 8 个 backward() 的 8 个批次相同电话,最后有一个step() 电话。
为了说明这个想法,这里是一个简单的例子。我们想让我们的张量x同时最接近[40,50,60]:
x = torch.tensor([1.0],requires_grad=True)
loss1 = criterion(40,x)
loss2 = criterion(50,x)
loss3 = criterion(60,x)
现在是第一种方法:(我们使用tensor.grad 来获取张量x 的当前梯度)
loss1.backward()
loss2.backward()
loss3.backward()
print(x.grad)
此输出:tensor([-294.])(编辑:将retain_graph=True 放在前两个backward 调用更复杂的计算图)
第三种方法:
loss = loss1+loss2+loss3
loss.backward()
print(x.grad)
再次输出:tensor([-294.])
第二种方法不同,因为我们在调用step() 方法后不调用opt.zero_grad。这意味着在所有 3 个step 调用中使用第一个backward 调用的梯度。例如,如果 3 个损失为相同的权重提供梯度 5,1,4,而不是 10 (=5+1+4),那么现在您的权重将具有 5*3+1*2+4*1=21 作为梯度。
进一步阅读:Link 1,Link 2