通常训练时:
batch_size = 32 → 一次前向+反向 → 更新参数显存不够时:
batch_size = 4 → 显存能放下,但 batch 太小,训练不稳定梯度累积的思想:
效果等价于:
等效 batch_size = mini_batch × accumulation_steps前向和反向照常算,但 optimizer.step() 延迟执行
mini_batch_size = 4
accumulation_steps = 8 # 等效 batch = 32
optimizer.zero_grad()for i, (x, y) in enumerate(dataloader):
x, y = x.to(device), y.to(device)
# 前向
pred = model(x)
loss = criterion(pred, y)
# 反向(注意 loss 要除以累积步数)
loss = loss / accumulation_steps
loss.backward()
# 累积到指定次数再更新
if (i + 1) % accumulation_steps == 0:
optimizer.step()
optimizer.zero_grad()✅ 关键点
loss / accumulation_steps:保证梯度尺度一致optimizer.zero_grad() 只在更新时清zero_gradloss.backward()
optimizer.zero_grad() # 错!梯度被清掉step() 前清loss.backward() # 等效 batch 变大但梯度没缩放| 技巧 | 作用 |
|---|---|
| 梯度累积 | 增大 batch |
| 混合精度 (AMP) | 显存 ↓ 30~50% |
| gradient checkpointing | 用时间换显存 |
| 减小 model / seq_len | 最直接 |
torch.no_grad() | 推理时省显存 |
effective_batch_size
= batch_per_step × accumulation_steps例如:
小显存 = 小 batch + 多累积 + 少更新
如果你愿意,我可以:
你现在是做什么任务?