假设:
Bb(b < B)accumulation_steps = B / b做法是:
accumulation_steps 次前向 + 反向accumulation_steps 次梯度accumulation_steps 次时 统一更新参数并清零梯度loss.backward()
optimizer.step()
optimizer.zero_grad()loss = loss / accumulation_steps
loss.backward() # 梯度累加
if (step + 1) % accumulation_steps == 0:
optimizer.step()
optimizer.zero_grad()accumulation_steps = 4
optimizer.zero_grad()
for i, (x, y) in enumerate(dataloader):
pred = model(x)
loss = criterion(pred, y)
# 1. 缩放 loss
loss = loss / accumulation_steps
# 2. 反向传播(梯度累加)
loss.backward()
# 3. 每 accumulation_steps 更新一次
if (i + 1) % accumulation_steps == 0:
optimizer.step()
optimizer.zero_grad()model.train()
optimizer.zero_grad()
accumulation_steps = 4
total_steps = 0
for epoch in range(epochs):
for batch_idx, (x, y) in enumerate(dataloader):
out = model(x)
loss = criterion(out, y) / accumulation_steps
loss.backward()
total_steps += 1
if total_steps % accumulation_steps == 0:
optimizer.step()
optimizer.zero_grad()| 目标 batch size | 单卡能跑 batch size | accumulation_steps |
|---|---|---|
| 64 | 16 | 4 |
| 128 | 8 | 16 |
| 32 | 32 | 1(不需要) |
有效 batch size =
per_gpu_batch_size × accumulation_steps × GPU数量例如:
会导致梯度放大,训练不稳定。
✅ 正确:
loss = loss / accumulation_steps❌ 每次 backward 都清梯度
梯度累积 不能完美模拟大 batch 的 BN 统计
解决方案:
SyncBatchNormtorch.nn.BatchNorm2d(..., momentum=...) 调小 momentum✅ 通常需要
经验规则:
lr_new = lr_base × sqrt(accumulation_steps)args = TrainingArguments(
per_device_train_batch_size=8,
gradient_accumulation_steps=4,
...
)梯度累积步数 = 目标 batch size ÷ 单步能跑的 batch size
核心就是:loss 缩放 + 梯度累加 + 定期更新
如果你愿意,可以告诉我:
我可以给你完全贴合你场景的设置方案。