36

Batch size 与梯度累加——一步看多少样本

阅读约 4 分钟第 36/60 课

到目前为止说的「一步」是:看一批数据 → 算 loss → 算梯度 → 更新参数。但「一批」到底是多少数据?

Batch size

Batch size 是每一步用来计算梯度的数据量。

Batch size = 1:每一步只看一个样本。梯度估计很不准确(一个样本不能代表整个数据集),更新方向抖动剧烈。但每一步很快,可以频繁更新。

Batch size = 1,000,000:每一步看一百万个样本。梯度估计非常准确(接近在整个数据集上算出来的真实梯度),更新方向非常稳定。但每一步需要处理一百万条数据,非常慢。

最佳 batch size 在两者之间。对语言模型来说,一个常见的范围是几十万到几百万个 token。

Sophia 的 batch size

Sophia 的 batch size 用 token 数量来衡量:每一步看约 50 万个 token(具体取决于序列长度和每批的序列数量)。

但 Sophia 是在单张 GPU 上训练的。一张 RTX 5090 的显存装不下 50 万个 token 的完整前向传播和反向传播——显存在存储中间激活值(前向传播时需要存下来给反向传播用)时就会溢出。

梯度累加

梯度累加(gradient accumulation)解决了这个问题。思路很简单:把一个大 batch 拆成多个小 batch,分多次前向和反向传播,把梯度累加起来,最后一次性更新参数。

# 假设目标 batch size 是 50 万 token,GPU 一次只能处理 5 万
# 就用 10 步梯度累加

optimizer.zero_grad()                 # 清空梯度

for i in range(10):                   # 10 个小 batch
    mini_batch = get_next_data()      # 取 5 万 token
    loss = model(mini_batch) / 10     # 前向传播,loss 除以 10(平均)
    loss.backward()                   # 反向传播,梯度累加到 .grad 上

optimizer.step()                      # 用累加后的梯度更新参数一次

10 个小 batch 的梯度累加起来,等价于在一个 50 万 token 的大 batch 上直接算梯度。数学上完全等价,只是实现上分成了多步。

这让 Sophia 能在单张 GPU 上实现跟多卡训练相当的有效 batch size。

这个单元学了什么

四个章节覆盖了训练节奏的核心概念:

  1. 学习率(第 33 章节):每步更新的步长。太大爆炸,太小不动。
  2. Warmup(第 34 章节):开始时从零逐步增大学习率,避免早期梯度不稳。
  3. Cosine decay(第 35 章节):后期逐步减小学习率,精细调整。
  4. Batch size 与梯度累加(本章节):每步看多少数据,以及怎么在有限显存下实现大 batch。

到这里,训练的「软件」部分全部讲完了——模型架构、损失函数、梯度、优化器、训练节奏。下一个单元进入「硬件」:数字在 GPU 上是怎么存储和计算的,以及怎么把一张显卡用满。