有一次,我训练一个图像分类模型,把 batch size 从 32 调到 512,满心期待训练更快收敛,结果验证集准确率反而掉了 2 个点。这个坑我踩了三次才想明白——batch size 不只是调节 GPU 利用率,它直接决定了模型学到的到底是什么。

批量大小到底是什么?
- 全批量梯度下降(Full Batch)
- 一次喂整个训练集,计算梯度最精确,但计算量爆炸,内存装不下,很少用。
- 随机梯度下降(SGD, batch size=1)
- 每次只喂一个样本,噪声巨大,收敛慢,但有时能跳出局部最优。
- 小批量梯度下降(Mini-batch)
- 折中方案,一次喂几十到几千个样本,用 GPU 并行加速,又保留一定噪声,是深度学习标配。
你可能会问:噪声这么大,为什么反而是好事?这就要说到梯度估计的方差了。
梯度估计的方差:小 batch 的“噪声”其实是好东西
模型每次更新参数,都是根据当前 batch 算出的梯度方向迈一步。batch 越小,这个梯度估计就越“糙”——它只是整体梯度的一个有偏快照。但正是这种糙,让模型有机会在损失曲面上 探索更多路径,不容易卡在尖锐的局部最优点。大 batch 的估计很稳定,步长方向更“正确”,却可能让模型一头扎进某个看起来很低、但周围全是悬崖的极小值——这种极小值对测试数据极其敏感,泛化性能差。
我最早单纯以为噪声是训练不稳定的元凶,想靠增大 batch size 来消除它。后来看 Keskar 等人 2016 年的论文 才明白,噪声其实是帮助模型找到 平坦极小值 的关键。他们用 CIFAR-10 实验发现,小 batch(256)测试准确率 74%,大 batch(10%)反而只有 72%,差距明显。
平坦极小值 vs 尖锐极小值:为什么小 batch 泛化更好
想象损失曲面是一片山地。大 batch 训练像一辆重卡,沿着最陡的方向直冲下去,往往停在坑底——但这个坑可能很窄,边缘陡峭,测试数据稍微偏移一点,损失就飙升。小 batch 训练像一辆颠簸的越野车,噪音让它不会精确停在同一个坑,反而更容易找到宽阔平坦的谷地。这种平坦区域对参数扰动不敏感,测试时鲁棒性更强。
Keskar 等人指出:“我们观察到,大 batch 方法倾向于收敛到损失函数表面的尖锐最小值,而小 batch 方法收敛到平坦最小值,这解释了泛化差距。”[来源]
学习率与 batch size 的线性缩放规则
增大 batch size 而不调整学习率,训练经常崩掉。因为梯度更新次数变少,总步长不足。一个实用的经验法则:当 batch size 增大 k 倍,学习率也增大 k 倍,可以保持训练动态相似。这来自 Goyal 等人 2017 年的论文,他们用这条规则在 ImageNet 上用 8192 的超大 batch 1 小时完成了训练,准确率不降。
# 示例:线性缩放
init_lr = 0.1 * (batch_size / 256) # 基准 batch 256 时学习率 0.1
但要注意,线性缩放有上限,batch size 过大(比如超过 8192)时,学习率太大反而导致发散,需要配合 warmup 策略。
梯度累积:穷人版的大 batch
GPU 显存装不下目标 batch size 怎么办?梯度累积 是个好办法:将大 batch 拆成多个小 batch,依次前向、反向,累积梯度,然后一次性更新参数。效果等同于大 batch 训练,只是速度慢些。
- 累积步数 = 目标 batch size / 实际每步 batch size
- 注意:累积的是梯度,不是损失;每步 loss 不能简单相加。
- 某些模块(如 BatchNorm)在累积时行为会变化,需要小心处理。
大 batch 训练一定不行吗?OpenAI 的实践
大 batch 并非一无是处。现代大模型(如 GPT-3)训练时就用了几百万 token 的 batch size,配合精细的学习率调度和大量数据,也能泛化良好。关键在于:大 batch 需要配套更强的正则化或更长的训练时间。OpenAI 用到了 GPT-3 论文 中提到的动态 batch size 递增策略,逐步从 32K 增加到 3.2M,同时调整学习率,平衡了训练速度和泛化。
我自己后来也发现,对于某些任务(如语言模型预训练),大 batch 带来的稳定梯度反而能加速收敛,只要在后期用小 batch 微调或增加 dropout,就能拉回泛化性能。
一张表说清大 batch 和小 batch 的区别
| 维度 | 小 batch(如 32) | 大 batch(如 512) |
|---|---|---|
| 梯度噪声 | 高,探索性强 | 低,方向更精确 |
| 收敛速度(每个 epoch) | 慢,更新次数多 | 快,每次更新基于更多样本 |
| 泛化性能 | 通常更好(平坦极小值) | 可能变差(尖锐极小值) |
| GPU 利用率 | 低,无法占满算力 | 高,矩阵运算更高效 |
| 所需学习率 | 较小 | 需线性放大 |
| 训练稳定性 | 可能震荡,但不易卡在差局部 | 更平滑,但可能过早收敛 |
常见误区速查
batch size 必须是 2 的幂吗?
不是,只是 GPU 对 2 的幂次计算更友好,实际效果差异不大。
小 batch 训练太慢怎么办?
用梯度累积模拟大 batch,或先用大 batch 预训练再小 batch 微调。
不同任务有最佳 batch size 吗?
CV 任务常用 32-256,NLP 微调常用 16-32,预训练则可能上万。没有绝对最优,需根据模型和显存试验。
增大 batch size 后验证 loss 震荡怎么办?
检查学习率是否线性放大,并加入 warmup,或适当降低学习率。
进阶:批次大小与学习率关系的数学直觉
参数更新公式:θ = θ – (η / B) Σᵢ ∇Lᵢ,其中 B 是 batch size。若 B 变 k 倍,保持 η/B 不变,即 η 也变 k 倍,则更新步长期望不变。但方差会随 B 增大而减小,这正是泛化差异的来源。
到这里,你应该已经理解了,batch size 不是“越大越好”的参数,而是调节 训练速度、稳定性和泛化性能 的三角旋钮。下次调参时,别再无脑拉满 batch size,先想想你的模型需要多少噪声来找到那条平坦的康庄大道。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/120.html