第三节:批次处理的核心三板斧——Batch Size、Epoch、Iteration
搞深度学习,这几个概念你要是没搞清楚,代码跑出来都是糊涂账。
我做项目那会儿带过一个新人,他训练模型时设了个 epoch=100,结果跑到第10个 epoch 就过拟合了。我问他为什么不再设小一点?他反问我:"epoch 不是轮数吗?跟过拟合有什么关系?" 嗯,问题就在这里——概念没吃透。
Batch Size:一口吃多少
说白了,batch size 就是一次喂给模型多少个样本。
你给模型准备了一万个样本。如果 batch size=32,那模型就是每32个样本算一次梯度,更新一次权重。
关键公式:
每次更新权重所需的样本数 = batch size
那 batch size 设多大才合适?我个人的经验是——看你的显存和模型收敛速度。下面这张表是我平时常用的判断依据:
| Batch Size | 特点 | 适合场景 |
|---|---|---|
| 1 | 随机梯度下降(SGD),噪音大,收敛慢 | 在线学习、样本量极小 |
| 16-64 | Mini-batch,平衡噪音与效率 | 绝大多数常见任务 |
| 128-512 | 大 batch,梯度估计更稳定 | 大规模训练、分布式场景 |
| 1024+ | 超大 batch,需配合学习率调整 | 超大规模数据集、预训练 |
避坑提醒:我曾经在某个图像分类任务里,把 batch size 从 32 翻到 256,结果模型精度直接掉了 2 个点。后来发现,大 batch 会让梯度更新更单调,容易陷入「糟糕」的局部极小值。这种情况下,你一般得配合学习率 warmup 或者更大的学习率来救场。
Epoch:完整过一遍数据
Epoch 的定义其实很简单——全部训练样本都过完一遍,就叫一个 epoch。
你有一万张图片,batch size=32,那么一个 epoch 就包含 10000 ÷ 32 = 312.5 次迭代。嗯,实际代码里会取整,一般会补足到 313 次。
为什么 epoch 多了容易过拟合?你想想看,模型每看一遍数据,就相当于复习一次。复习次数太多,它就学会死记硬背了,泛化能力反而下降。我在做 NLP 任务时遇到过这情况,把 epoch 从 10 改到 5,测试集 F1 反倒涨了 0.03。
我的习惯:先跑 5 个 epoch 看看损失曲线。如果验证集损失还在下降,再试着加;如果已经开始走平或上翘,马上停。别傻乎乎地跑完预设的 100 个 epoch。
Iteration:一次更新算一步
Iteration 就是模型做一次前向传播 + 一次反向传播。
一次迭代 = 处理一个 batch 的样本 + 更新一次权重。
举个例子,你设 epoch=10,batch size=32,总样本 10000,那总的迭代次数就是:
总迭代次数 = epoch × (总样本数 ÷ batch_size)
= 10 × (10000 ÷ 32)
= 10 × 312.5
≈ 3130 次
这个数值你在训练日志里经常能看见,比如常见的输出:
Epoch [1/10], Iteration [100/313], Loss: 0.23
Epoch [1/10], Iteration [200/313], Loss: 0.19
...
这三者的关系,我用一张图说明白
下面这张 SVG 图把 batch size、epoch、iteration 的流程和关系给你梳理清楚了。我觉得这是理解整章知识体系最直观的方法。
实战中的参数设置
说了这么多理论,实际代码里怎么设?我习惯用 PyTorch,举个小例子:
from torch.utils.data import DataLoader
# 假设你的 dataset 有 10000 个样本
dataset = YourDataset()
# batch_size 设成 32
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
# epoch 设成 10
num_epochs = 10
for epoch in range(num_epochs):
for i, (inputs, labels) in enumerate(dataloader):
# 每次循环就是一次 iteration
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
optimizer.zero_grad()
经验之谈:写代码时你经常能看到这样的打印日志——
Epoch 5/10 - Iteration 1500/3130 - loss: 0.2134
你知道这代表什么意思吗?模型已经看了 5 遍全部数据,目前正在进行第 1501 次参数更新。这就是实时监控训练进度的基本功。
避坑要点
- Epoch 太多不一定好:我在 CV 竞赛里吃过这个亏。光调 epoch 就跑崩了验证集,后来改用 early stopping 才稳住。
- Batch size 太大会影响泛化:大 batch 的梯度噪音小,但容易收敛到尖锐的极小值。你可以试试学习率 warmup 或动态调整。
- Iteration 的计数不要搞混:有些框架从 0 开始计,有些从 1 开始。你查日志时务必确认一下,不然容易误解训练进度。
说白了,batch size、epoch、iteration 就是三个决定模型怎么学、学多快、学几遍的参数。搞懂了它们,你写代码和调参时就不会——嗯,就不会两眼一抹黑了。