什么是梯度累积技术原理

GPU
小华
2026-08-17

梯度累积(Gradient Accumulation)是一种在显存受限情况下,实现大批次(large batch)训练的常用技术。它的核心思想是:把多次小批次(mini-batch)的梯度先累加起来,再统一做一次参数更新

下面从原理、动机、实现步骤和注意事项几个方面说明。

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

在深度学习中,训练通常按如下步骤进行:

  1. 前向传播(forward)
  2. 计算损失(loss)
  3. 反向传播(backward),计算梯度
  4. 优化器更新参数(step)

通常:

  • batch size 越大 → 梯度估计越稳定,收敛更快
  • batch size 受限于显存(GPU memory)

于是出现矛盾:

想用大 batch,但显存放不下
梯度累积就是解决这个问题的方案。

二、梯度累积的核心原理

1️⃣ 正常训练(无梯度累积)

假设真实想用的 batch size 是 B,但显存只能放 bb < B)。
正常训练一次更新:

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

一次 forward + backward 就更新一次参数。

2️⃣ 使用梯度累积

把大 batch 拆成 k = B / b 个小 batch:

  • 每个小 batch 做前向和反向
  • 不立即更新参数
  • 把梯度累加到 .grad
  • 累积 k 次后,再统一更新

等价于:

B 个样本算一次梯度,再更新一次参数

三、数学原理

假设损失函数是:
[
mathcal{L} = frac{1}{B} sum_{i=1}^{B} ell(x_i)
]
显存限制下,我们分成 k 步:
[
g_t = frac{1}{b} sum_{i in text{batch}_t} nabla ell(x_i)
]
梯度累积时:
[
G = sum_{t=1}^{k} g_t
]
最终更新:
[
theta leftarrow theta - eta cdot G
]

✅ 这与一次性用 B 个样本算梯度是数学等价的(不考虑数值误差)

四、实现方式(以 PyTorch 为例)

✅ 伪代码

accumulation_steps = 4  # 累积 4 次
optimizer.zero_grad()
for i, (x, y) in enumerate(dataloader):
pred = model(x)
loss = criterion(pred, y)
# 梯度归一化(很重要)
loss = loss / accumulation_steps
loss.backward()
if (i + 1) % accumulation_steps == 0:
optimizer.step()
optimizer.zero_grad()

✅ 关键点

  1. loss 除以累积步数
  • 保证梯度大小等价于大 batch
  1. 只在累积结束后 optimizer.step()
  2. zero_grad() 在 step 后调用

五、梯度累积 vs 大 Batch 的细微差别

对比项大 Batch梯度累积
梯度计算一次多次累加
显存占用
数值结果几乎一致几乎一致
BN 行为不同可能不同

⚠️ Batch Normalization 是例外

  • BN 的统计量(mean/var)是每个小 batch 独立计算的
  • 梯度累积 ≠ 真正的大 batch BN

✅ 解决方案:

  • 使用 梯度累积 + 同步 BN
  • 或改用 LayerNorm / GroupNorm

六、适用场景

✅ 非常适合:

  • 大模型(LLM、ViT、Diffusion)
  • 显存不足但想稳定训练
  • 多卡训练时模拟更大 batch

❌ 不太适合:

  • 对 BN 非常敏感的任务
  • 极度追求训练速度(累积会增加 step 数)

七、一句话总结

梯度累积的本质是:在显存受限的情况下,通过多次前向-反向传播“攒梯度”,最终模拟一次大 batch 的参数更新。
如果你愿意,我也可以:
  • 公式 + 图示再讲一遍
  • 对比 梯度累积 vs 梯度检查点(Gradient Checkpointing)
  • 结合 大模型训练(LLM) 讲实际工程经验
亿速云提供售前/售后服务

售前业务咨询

售后技术保障

400-100-2938

7*24小时售后电话

官方微信小程序