【发布时间】:2021-04-26 18:35:32
【问题描述】:
我正在一个相对较小的数据集上训练 BERT 模型,并且不能丢失任何标记样本,因为它们必须全部用于训练。由于 GPU 内存的限制,我使用梯度累积来训练更大的批次(例如 32)。根据PyTorch documentation,梯度累加的实现方式如下:
scaler = GradScaler()
for epoch in epochs:
for i, (input, target) in enumerate(data):
with autocast():
output = model(input)
loss = loss_fn(output, target)
loss = loss / iters_to_accumulate
# Accumulates scaled gradients.
scaler.scale(loss).backward()
if (i + 1) % iters_to_accumulate == 0:
# may unscale_ here if desired (e.g., to allow clipping unscaled gradients)
scaler.step(optimizer)
scaler.update()
optimizer.zero_grad()
但是,如果您正在使用例如110 个训练样本,batch size 8 和累积 step 4(即有效批大小 32),这种方法只会训练前 96 个样本(即 32 x 3),即浪费 14 个样本。为了避免这种情况,我想将代码修改如下(注意更改为最终的 if 语句):
scaler = GradScaler()
for epoch in epochs:
for i, (input, target) in enumerate(data):
with autocast():
output = model(input)
loss = loss_fn(output, target)
loss = loss / iters_to_accumulate
# Accumulates scaled gradients.
scaler.scale(loss).backward()
if (i + 1) % iters_to_accumulate == 0 or (i + 1) == len(data):
# may unscale_ here if desired (e.g., to allow clipping unscaled gradients)
scaler.step(optimizer)
scaler.update()
optimizer.zero_grad()
这是正确的,真的那么简单,还是会有任何副作用?这对我来说似乎很简单,但我以前从未见过它。任何帮助表示赞赏!
【问题讨论】:
-
嗨 Andrea,据我所知,如果在您的数据加载器中使用 drop_last=False,它将在训练结束时创建一个较小的批次(包含剩余的样本)。因此,我认为在开始这个 for 循环之前将 iter_to_accumulate 增加 1 应该可以解决它。
-
查看我对 Shai 的回复。我不确定这如何回答我的问题
标签: python machine-learning deep-learning nlp pytorch