0

我试图在训练期间只为那些损失小于前一批获得的损失的批次更新模型的权重。

因此,在批处理循环中,我存储了每次迭代获得的损失,然后我尝试评估一个条件:如果时间 t-1 的损失小于时间 t,那么我继续如下:

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

然后,在 else 部分什么都不应该做。尽管如此,我收到一条错误消息,说 CUDA 内存不足。

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

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

有没有办法做到这一点?

4

2 回答 2

1

这是存储连续步骤的损失时的常见问题。内存不足错误是因为您将损失存储在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
于 2021-08-09T10:22:21.983 回答
1

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

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

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

于 2021-08-09T11:22:06.257 回答