仅当当前批次的损失小于先前批次时如何更新模型的权重

How to update the weights of a model only if loss for current batch is smaller than previous

我正在尝试仅在训练期间更新模型的权重,这些批次的损失小于前一批次获得的损失。

所以,在 batches 循环中,我存储了每次迭代获得的损失,然后我尝试评估一个条件:如果时间 t-1 的损失小于时间 t,那么我进行如下操作:

if loss[t-1] <= loss[t]:
  loss.backward()
  optimizer.step()
else:
  #do nothing  or what ?

那么else部分什么都不要做。 None不过,我收到一条错误消息,提示 CUDA 运行 内存不足。

当然,在计算损失之前,我执行了一个optimizer.zero_grad()语句。

批量运行的 for 循环似乎 运行 没问题,但内存使用量激增。我读到也许将梯度设置为 None 会阻止权重更新过程,但我尝试了很多句子(output.clone().detach()optimizer.zero_grad(set_to_none=True))但我不确定它们是否有效。我认为他们没有。 None尽管如此,内存使用爆炸仍然发生。

有没有办法做到这一点?

这是存储连续步骤的损失时的常见问题。 内存不足错误是因为您将损失存储在 list 中。只要您保留对损失的引用,计算图仍将保留并保留在内存中。一个简单的解决方法是在将张量附加到 list:

时分离张量
# loss = loss_fn(...)
losses.append(loss.detach())

然后你可以使用

if losses[t] <= losses[t-1]: # current loss is smaller
    losses[t].backward()
    optimizer.step()
else:
    pass

将损失存储在列表中将为损失中的每个元素存储该批次的整个图形。相反,您可以执行以下操作:

losses.append(loss.cpu().tolist())
optimizer.zero_grad()
if losses[-1] <= losses[-2]: # current loss is smaller
    loss.backward()
    optimizer.step()

由于您仅在当前损失小于前一个损失时才更新模型,因此您实际上不需要存储所有损失。最后一个和上一个的值就够了。否则,如果您想存储有限数量的图形,则需要注意可用内存,这在许多应用程序中都非常有限。