SGD 中权重更新的梯度均值或总和

机器算法验证 神经网络 优化 反向传播 随机梯度下降
2022-03-15 13:08:26

我正在使用 PyTorch 中的神经网络实现使用单个观察来计算损失。我对 SGD 的一个小细节感到困惑。如果我计算 loss 并做loss.backward(),我正在累积梯度。如果我对 100 次观察执行此操作然后运行optimizer.step(),我应该平均梯度吗?

这就是我现在正在做的事情:

def compute_loss(training_data):
  for data in training_data:
    loss = F.mse_loss(data[0], data[1])
    loss.backward()

def optimize(sample):
  optimizer.zero_grad()
  compute_loss(sample)
  optimizer.step()

应该是:

def compute_loss(training_data):
  for data in training_data:
    loss = F.mse_loss(data[0], data[1])
    loss.backward(torch.Tensor([1.0/len(training_data)]))
1个回答

下面假设一个损失函数f这表示为总和,而不是平均值将损失表示为平均值意味着缩放1n已“烘烤”,无需进一步操作。特别要注意的是,默认情况下F.mse_loss使用reduction="mean",所以对于 OP 的代码,不需要进一步修改来实现平均梯度。事实上,重新调整梯度使用reduction="mean"并不能达到预期的效果,并且相当于将学习率降低了 1 倍1n.


假设G=i=1nf(xi)是一些小批量的梯度之和n样品。使用学习率(步长)的 SGD 更新r

x(t+1)=x(t)rG.

现在假设您使用梯度的平均值这将更改更新。如果我们使用学习率r~, 我们有

x(t+1)=x(t)r~nG.
通过重新缩放,可以使这些表达式相等r或者r~. 所以从这个意义上说,均值和总和之间的区别并不重要,因为r由研究人员在任何一种情况下选择,并选择一个好的r因为总和有一个等价的,重新调整的r~为平均值。

然而,更喜欢使用平均值的一个原因是,这将学习率和小批量大小解耦,因此改变小批量中的样本数量不会隐含地改变学习率。

请注意,使用minibatch的平均值而不是整个训练集是标准的。然而,上面相同的重新缩放参数也适用于这里——如果你正在调整学习率,对于一个固定大小的数据集,你会发现一个工作良好的学习率,并且这个学习率可以重新缩放以适合使用总和代替某些平均值的梯度下降。