如何详解梯度累积技术

GPU
小华
2026-08-17

梯度累积(Gradient Accumulation)是深度学习中一种在显存受限时模拟大 batch size 训练的常用技术。下面从动机、原理、数学推导、训练流程、代码示例、优缺点与常见误区等方面系统详解。

一、为什么需要梯度累积?

1. 大 batch size 的好处

  • 梯度估计更稳定
  • 某些任务(如对比学习、检测、大模型)需要较大 batch size
  • 分布式训练中通信效率更高

2. 显存限制

  • 显存占用 ≈ 模型参数 + 前向激活值 + 梯度 + 优化器状态
  • batch size 越大,激活值占用显存越大
  • 单卡显存有限,无法一次塞入大 batch

3. 梯度累积的核心思想

把“大 batch”拆成多个“小 batch”,多次前向+反向,累积梯度后再更新参数

二、梯度累积的数学原理

1. 标准训练(无累积)

设真实 batch size = (B),损失函数:
[
mathcal{L} = frac{1}{B} sum_{i=1}^{B} ell(x_i, y_i)
]
梯度:
[
g = nabla_theta mathcal{L}
]
参数更新:
[
theta_{t+1} = theta_t - eta cdot g

]

2. 使用梯度累积

将大 batch 拆成 (K) 个小 batch,每个小 batch 大小为 (b),满足:
[
B = K times b
]

第 k 个小 batch 的梯度:

[
g_k = nabla_theta frac{1}{b} sum_{i in text{batch}_k} ell(x_i, y_i)
]

累积梯度:

[
g_{text{acc}} = sum_{k=1}^{K} g_k
]

实际更新时:

[
theta_{t+1} = theta_t - eta cdot frac{g_{text{acc}}}{K}

]

3. 关键点

  • 累积的是梯度,而不是 loss
  • 最终等价于 大 batch 的平均梯度
  • 只要优化器是线性更新(SGD / Adam 本质也是),数值上是一致的

三、训练流程对比

1. 普通训练流程

for batch in dataloader:
optimizer.zero_grad()
loss = model(batch)
loss.backward()
optimizer.step()

2. 梯度累积流程

accumulation_steps = K
optimizer.zero_grad()
for i, batch in enumerate(dataloader):
loss = model(batch)
loss = loss / accumulation_steps   # 除以 K
loss.backward()
if (i + 1) % K == 0:
optimizer.step()
optimizer.zero_grad()

四、为什么要在 backward 前除以 K?

方式一(推荐 ✅)

loss = loss / accumulation_steps
loss.backward()

✅ 优点:

  • 数值稳定
  • 与混合精度训练兼容
  • 与 loss scaling 不冲突

方式二(不推荐 ❌)

loss.backward()
if step % K == 0:
for p in model.parameters():
p.grad /= K

❌ 缺点:

  • 容易忘记处理 grad
  • 混合精度下容易出问题

五、代码示例(PyTorch)

model.train()
optimizer.zero_grad()
accumulation_steps = 4
for step, (x, y) in enumerate(dataloader):
x, y = x.cuda(), y.cuda()
pred = model(x)
loss = criterion(pred, y)
loss = loss / accumulation_steps     # 关键
loss.backward()
if (step + 1) % accumulation_steps == 0:
optimizer.step()
optimizer.zero_grad()

六、梯度累积 ≠ 完全等价大 batch 的情况

1. Batch Normalization(⚠️重点)

BN 的行为依赖于当前 batch 的统计信息:

  • 普通大 batch:BN 用整个大 batch 的 mean/var
  • 梯度累积
  • 每个小 batch 独立计算 BN
  • 等价于多个小 batch 的 BN,不是真正的大 batch BN

✅ 解决方案:

  • 使用 SyncBatchNorm
  • 使用 梯度累积 + 冻结 BN
  • 或改用 LayerNorm / GroupNorm

2. 学习率与 warmup

  • 梯度累积后:
  • 真实 batch size 变大
  • 学习率通常需要相应增大
  • 否则训练可能变慢或欠拟合

经验法则:

学习率 ∝ 有效 batch size

七、优缺点总结

✅ 优点

  • 显存占用低
  • 可模拟大 batch 训练
  • 实现简单
  • 对大多数任务有效

❌ 缺点

  • BN 行为不一致
  • 训练 step 变慢(时间不变,但更新次数减少)
  • 调试时容易忘记 zero_grad

八、常见误区

误区正确
loss 不除 K必须除
每个 step 都 step每 K 次才 step
累积 loss 而不是梯度累积的是梯度
BN 不受影响BN 会受影响

九、一句话总结

梯度累积 = 多次前向反向 + 梯度求和 + 延迟参数更新,用来在有限显存下模拟大 batch 训练。
如果你愿意,我也可以:
  • 结合 混合精度(AMP) 讲梯度累积
  • 对比 梯度累积 vs 分布式训练
  • 优化器(Adam)角度推导为什么等价
  • 给你一个 完整可运行训练模板

只要告诉我你当前的使用场景即可。

亿速云提供售前/售后服务

售前业务咨询

售后技术保障

400-100-2938

7*24小时售后电话

官方微信小程序