在本文中,我们试图更好地理解批量大小对训练神经网络的影响。具体而言,我们将涵盖以下内容:
什么是Batch Size?
为什么Batch Size很重要?
小批量和大批量如何凭经验执行?
为什么大批量往往性能更差,如何缩小性能差距?
什么是Batch Size?
训练神经网络以最小化以下形式的损失函数:
点击并拖拽以移动
theta 代表模型参数
m 是训练数据样本的数量
i 的每个值代表一个单一的训练数据样本
J_i 表示应用于单个训练样本的损失函数
通常,这是使用梯度下降来完成的,它计算损失函数相对于参数的梯度,并在该方向上迈出一步。随机梯度下降计算训练数据子集 B_k 上的梯度,而不是整个训练数据集。
点击并拖拽以移动
B_k 是从训练数据集中采样的一批,其大小可以从 1 到 m(训练数据点的总数)。这通常称为批量大小为 |B_k| 的小批量训练。我们可以将这些批次级梯度视为“true”梯度的近似值,即整体损失函数相对于 theta 的梯度。
我们使用小批量是因为它倾向于更快地收敛,因为它不需要完全遍历训练数据来更新权重。
为什么Batch Size很重要?
Keskar 等人指出,随机梯度下降是连续的,且使用小批量,因此不容易并行化 。使用更大的批量大小可以让我们在更大程度上并行计算,因为我们可以在不同的工作节点之间拆分训练示例。这反过来可以显着加快模型训练。
然而,较大的批大小虽然能够达到与较小的批大小相似的训练误差,但往往对测试数据的泛化效果更差 。训练误差和测试误差之间的差距被称为“泛化差距”。
因此,“holy grail”是使用大批量实现与小批量相同的测试误差。这将使我们能够在不牺牲模型准确性的情况下显着加快训练速度。
实验是如何设置的?
我们将使用不同的批量大小训练神经网络并比较它们的性能。
数据集:我们使用 Cats and Dogs 数据集,该数据集包含 23,262 张猫和狗的图像,在两个类之间的比例约为 50/50。由于图像大小不同,我们将它们全部调整为相同大小。我们使用 20% 的数据集作为验证数据,其余作为训练数据。
评估指标:我们使用验证数据上的二元交叉熵损失作为衡量模型性能的主要指标。
点击并拖拽以移动
来自 Cats vs Dogs 数据集的示例图像
基础模型:定义了一个受 VGG16 启发的基础模型,在其中重复应用 (convolution ->max-pool) 操作,使用 ReLU 作为卷积的激活函数。然后,将输出量展平并将其送入两个完全连接的层,最后是一个带有 sigmoid 激活的单神经元层,产生一个介于 0 和 1 之间的输出,它表明模型是预测猫(0)还是 狗 (1).
训练:使用学习率为 0.01 的 SGD。一直训练到验证损失在 100 次迭代中都没有改善为止。
Batch Size如何影响训练?
点击并拖拽以移动
不同批次大小的训练和验证损失曲线
点击并拖拽以移动
每个批次大小获得的最佳损失
点击并拖拽以移动
左:每个epoch的平均时间。中间:直到验证损失收敛的epochs 数量。右图:直到验证损失收敛的总训练时间。
从上图中,我们可以得出结论,batch size越大:
训练损失减少的越慢。
最小验证损失越高。
每个时期训练所需的时间越少。
收敛到最小验证损失所需的 epoch 越多。
让我们一一了解这些。首先,在大批量训练中,训练损失下降得更慢,如红线(批量大小 256)和蓝线(批量大小 32)之间的斜率差异所示。
其次,大批量训练比小批量训练实现更糟糕的最小验证损失。例如,批量大小为 256 的最小验证损失为 0.395,而批量大小为 32 时为 0.344。
第三,大批量训练的每个 epoch 花费的时间略少——批量大小 256 为 7.7 秒,而批量大小 256 为 12.4 秒,这反映了与加载少量大批量相关的开销较低,而不是许多小批量依次。如果我们使用多个 GPU 进行并行训练,这种时间差异会更加明显。
然而,大批量训练需要更多的 epoch 才能收敛到最小值——批量大小 256 为 958,批量大小 32 为 158。因此,大批量训练总体上花费的时间更长:批量大小 256 花费的时间几乎是 32 的四倍!请注意,我们没有在这里并行化训练——如果我们这样做了,那么大批量训练的训练速度可能与小批量训练一样快。
如果我们并行化训练运行会发生什么?为了回答这个问题,我们使用 TensorFlow 中的 MirroredStrategy 在四个 GPU 上并行训练:
with tf.distribute.MirroredStrategy().scope():
Create, compile, and fit model
…
点击并拖拽以移动
MirroredStrategy 将模型的所有变量复制到每个 GPU,并将前向/后向传递计算批量分发到所有 GPU。然后,它使用 all-reduce 组合来自每个 GPU 的梯度,然后将结果应用于每个 GPU 的模型副本。本质上,它正在划分批次并将每个块分配给 GPU。
我们发现并行化使每个 epoch 的小批量训练速度稍慢,而它使大批量训练速度更快——对于 256 批大小,每个 epoch 需要 3.97 秒,低于 7.70 秒。然而,即使有 per-epoch 加速,它也无法在总训练时间方面匹配批量大小 32——当我们乘以总训练时间 (958) 时,我们得到大约 3700 秒的总训练时间,即 仍然远大于批大小 32 的 1915 秒。
点击并拖拽以移动
当跨 4 个 GPU 并行时,每个 epoch 的平均时间。
到目前为止,大批量训练看起来并不值得,因为它们需要更长的时间来训练,并且训练和验证损失更严重。为什么会这样?有什么办法可以缩小性能差距吗?
为什么较小的批量性能更好?
Keskar 等人对小批量和大批量之间的性能差距提出了一种解释:使用小批量的训练倾向于收敛到平坦的极小化,该极小化在极小化的小邻域内仅略有变化,而大批量则收敛到尖锐的极小化,这变化很大。平面minimizers 倾向于更好地泛化,因为它们对训练集和测试集之间的变化更加鲁棒 。
点击并拖拽以移动
取自 Keskar 等人 的平坦和尖锐最小值的概念图。
此外,他们发现与大批量训练相比,小批量训练可以找到距离初始权重更远的最小值。他们解释说,小批量训练可能会为训练引入足够的噪声,以退出锐化minimizers 的损失池,而是找到可能更远的平坦minimizers 。
参考资料:
https://baijiahao.baidu.com/s?id=1715190772611543607
https://baijiahao.baidu.com/s?id=1715196797886025535
https://zhuanlan.zhihu.com/p/427997311
https://www.zhihu.com/question/66013888/answer/2200289980
https://www.zhihu.com/question/65869469/answer/2199876343
https://www.zhihu.com/question/268272958/answer/2199868349
https://www.zhihu.com/question/395916414/answer/2199803541
https://haokan.baidu.com/v?pd=bjh&vid=1889531042157625509
https://www.360kuai.com/pc/detail?url=http%3A%2F%2Fzm.news.so.com%2F967c1915b900bb66bf237901ebb29061&check=7f50029076beb31e
https://www.yidianzixun.com/article/0YXXo6Dg
http://www.77l.com/news/guide/244251.html
https://www.40407.com/zixun/42359.html
https://www.juxia.com/sjwy/zixun-34100.html
https://www.zcool.com.cn/article/ZMTMxMjY4NA==.html