梯度累积(Gradient Accumulation)是一种在显存有限的情况下,模拟大 batch size 训练的技术。其核心思想是:在多个小 batch 上分别计算梯度,但不立即更新参数,而是把梯度累加起来,累积到一定步数后再一次性更新模型参数并清空梯度。
假设:
NM(M < N)K = N / M训练流程变为:
N 个样本计算梯度。accumulation_stepsloss.backward()(梯度自动累加)accumulation_steps 次:optimizer.step()optimizer.zero_grad()⚠️ 注意:
loss 通常需要除以 accumulation_steps(或 batch size),避免梯度尺度不一致zero_grad() 只在累积结束后调用model.train()
optimizer.zero_grad()
accumulation_steps = 4
for i, (inputs, targets) in enumerate(dataloader):
outputs = model(inputs)
loss = criterion(outputs, targets)
# 梯度累积时,loss 要归一化
loss = loss / accumulation_steps
loss.backward()
# 每 accumulation_steps 更新一次
if (i + 1) % accumulation_steps == 0:
optimizer.step()
optimizer.zero_grad()model.train()
optimizer.zero_grad()
accumulation_steps = 4
total_loss = 0.0
for epoch in range(num_epochs):
for i, (inputs, targets) in enumerate(dataloader):
outputs = model(inputs)
loss = criterion(outputs, targets) / accumulation_steps
loss.backward()
total_loss += loss.item()
if (i + 1) % accumulation_steps == 0:
optimizer.step()
optimizer.zero_grad()
print(f"Step {i+1}, Loss: {total_loss:.4f}")
total_loss = 0.0| 实际 batch size | 累积步数 | 等效 batch size |
|---|---|---|
| 16 | 4 | 64 |
| 8 | 8 | 64 |
⚠️ 注意:
torch.nn.SyncBatchNormLayerNorm / GroupNormfrom torch.cuda.amp import autocast, GradScaler
scaler = GradScaler()
optimizer.zero_grad()
accumulation_steps = 4
for i, (inputs, targets) in enumerate(dataloader):
with autocast():
outputs = model(inputs)
loss = criterion(outputs, targets) / accumulation_steps
scaler.scale(loss).backward()
if (i + 1) % accumulation_steps == 0:
scaler.step(optimizer)
scaler.update()
optimizer.zero_grad()torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)optimizer.step() 前执行。✅ 显存不足
✅ 想用大 batch size 提升稳定性
✅ 训练大模型(LLM、ViT、Diffusion)
❌ 不适合:
如果你愿意,我可以:
只要把你的代码或框架告诉我即可。