设置 BatchSize

BatchSize 是非常重要的超参数,它不仅影响训练速度,也影响模型精度。本篇来讨论如何选择 BatchSize。

BatchSize 是否越大越好?

BatchSize 一般指同时代入训练模型的实例个数,最直接的经验是如果 GPU 显存不大,又设置较大的 BatchSize 时直接报错“cuda runtime error(2): out of memory”。

是不是只要机器性能允许,就要设置尽可能大的 Batch size 呢?同时训练多个实例比逐个代入单个实例训练速度又能提高多少?

下图为使用不同的 batchSize,在 LeNet 上训练 mnist 数据的效果,使用的框架为 Theano。

可以看到,使用较大的 batchSize 的确可以提速,但是 batchSize 大到一定程度后,效果并不十分明显。

从图中可以看到如果将所有数据全部代入一次迭代(左图),则在训练集上的代价函数下降比较平滑,如果切分成多个 Batch,代价函数不一定是下降的。这是由于每一个 Batch 中数据的难度不同,造成了代价函数忽大忽小。

如何选择 batch 大小?

两种极端的情况是 BatchSize 大小为 1,每次只训练一个实例,或者 BatchSize 大小等于所有训练集数据大小,即每次训练所有数据。但更多的时候 BatchSize 设置在二者之间。

batchSize 较小时,抖动大,训练过程有很大运气的成份,可能某个实例将模型带偏了,防止被模型被带偏的方法是使用较小的学习率,这样即非并行处理,又使用较小的学习率,使得收敛变慢。

batchSize 较大时,任务并行执行,训练速度快, 且大 Batch 正负样本更均衡可以有效更新 BN 层参数精度更高。代价函数也能相对比较稳定,平滑地下降。但是如果代入了所有数据后再调参,可能会使很多梯度相互抵消,调参也比较粗糙。如果不进行特殊处理,过大的 BatchSize 一将会损失模型精度。另外,较大的 batchSize 会使模型的泛化能力下降(generalization gap)。

如果遇到较大的数据集,一般需要切分成 batch 分批训练,对于较少的数据,也可以使用全部数据训练。当有足够算力时,选取 BatchSize 为 32,64,128 或更小一些的 batch_size。算力不够时,在效率和泛化性之间做权衡,选择更小的 batchSize。

在训练过程中,可以将 batch_size 作为超参数做多次尝试。另一方面,也可以在前期使用较大的学习率和较越 BatchSize 粗调,后期(比如论文实验/比赛最后)将 BatchSize 变小精调,并使用 SGD 优化方法,慢慢把 Error 磨低。

BatchSize 是否只与速度有关?

BatchSize 不仅与速度相关,如果模型中使用了 Batch Normalization(BN)归一化方法,那么太小的 BatchSize 会影响模型效果,如果受算法或性能限制只能使用小的 BatchSize,则建议在 fine-tune 时锁住 BN 归一化层,或者使用其它归一化方法(如 Group Normalization)。

另外,BN 归一化时的统计值针对每一 Batch 计算,而非对整个训练集计算,从而引入了噪声,当噪声在合理范围以内时,它能实现类似 Dropout 的效果,使模型更加健壮;BatchSize 太小噪声太大,则使模型效果变差;如果 BatchSize 太大,统计值能有效地表示整体训练数据的统计数据,则无法产生类似 Dropout 的正则化效果。

BatchSize 与 Learning rate 的关系

Krizhevsky 提出,如果 BatchSize 加大,可以加大学习率,当 BatchSize 加大 k 倍,则学习也加大 k 的开根号位数,后来发现使用线性变换调节二者关系效果更好。用这种方法将 AlexNet 的 BatchSize 从 128 加大到 1024 精度只损失 1%。但是太大的学习率又会在一开始使模型训练不稳定,解决该问题的方法是学习率 warm-up。