批量训练

数据量大了,每次喂全量太慢,把数据切成小块,让训练又快又稳。

知识课 · 约 25 分钟 · 更新于 2026-07-14

回顾:每次更新都用全部数据?

到目前为止,所有训练循环都是这样写的:

把 全部 N 个样本 都过一遍,求平均 loss,再做 一次 参数更新。 这种做法叫 批量梯度下降 (Batch Gradient Descent,简称 BGD)。

它的 好处 很直接,梯度是 全量平均 , 估计精确、噪声小,loss 曲线最稳定,但代价也很明显:

  • 慢 :当 N 很大(百万级),每一步都要算上百万次前向 + 反向, 一个 epoch 才能动一次参数
  • 容易卡住 :损失曲面光滑无噪, 一旦掉到 局部最小值 附近梯度变小,就难以逃脱

另一个极端:随机梯度下降

既然全量更新慢,那干脆每次只用 一个样本 更新一次:

这就是 随机梯度下降 (Stochastic Gradient Descent,SGD)。

它的 好处 是 更新最频繁、单步最便宜 , N 个样本就有 N 次参数更新,每一步只需要算一条样本的前向 + 反向, 但代价也很明显:

  • 梯度噪声大 :单样本梯度方向极不稳定, loss 曲线呈剧烈震荡,难以判断是否真正收敛
  • 浪费 GPU 算力 :GPU 一次能并行算上百条样本, 单条单条地喂,发挥不出这部分并行能力

最佳折中:mini-batch SGD

实际使用的是两者的折中,每次取 一小批 样本(比如 32 / 64 / 128 条) 计算平均梯度后更新:

式子里的 就是这一批的样本数,它有个专门的名字叫 batch_size (批量大小),是 mini-batch SGD 中最常见的超参之一,决定了每次参数更新一起参与计算的样本数。

这就是 mini-batch SGD ,是当今所有深度学习训练的默认选择。 它兼顾了 BGD 的稳定性与 SGD 的效率,并且能充分利用 GPU 的并行能力, 一个 batch 一次性算完,吞吐远超单样本逐个算。

batch_size 的影响规律

越大,单步算的样本越多、梯度越接近全量平均; 越小则相反。所以选 32 还是 256 还是 1024 并非随意,这个超参的影响有迹可循:

经验规律是, 显存允许时选择更大的 batch ,但不必一味追求更大; 小 batch 带来的梯度噪声,反而有助于跳出尖锐的局部最小值。

PyTorch 数据加载工具链

要做 mini-batch 训练,需要把数据切片成 batch 一个个喂给模型。 PyTorch 提供两个核心工具:

  • Dataset :定义"一份数据怎么取",给定索引返回一对
  • DataLoader :自动把 Dataset 按 batch_size 切片、打乱、并行预取

重写训练循环

加上 batch 维度后,训练循环变成 外层 epoch + 内层 batch 的双层循环:

Playground:batch_size 对比实验

选择不同的 batch 大小,点击「训练一次」,下方折线图会按颜色叠加每次试验的 loss 曲线。

观察: batch=1 时单步用单样本梯度,loss 曲线锯齿剧烈; batch=32 已显著平滑; batch=256 的曲线几乎是一条平滑下降线,非常接近 全量 训练。

附录:张量批量操作语法

引入 batch 维度后,张量普遍会多出一个维度(典型形状 )。 所谓「批量友好」是指:这些工具能自动按 batch 维并行计算, 让你不必为 batch 写 for 循环。下面是几个最常被提到的:

记号约定 :下表中 始终表示 batch 维;其他大写字母( 、 、 、 )表示 样本本身 的维度, 与 batch 无关。