批量标准化和辍学的顺序?

Posted

技术标签:

【中文标题】批量标准化和辍学的顺序?【英文标题】:Ordering of batch normalization and dropout? 【发布时间】:2022-01-06 22:25:43 【问题描述】:

最初的问题是关于 TensorFlow 实现的。但是,答案是针对一般实现的。这个通用答案也是 TensorFlow 的正确答案。

在 TensorFlow 中使用批量标准化和 dropout(特别是使用 contrib.layers)时,我需要担心排序吗?

如果我使用 dropout,然后立即进行批量标准化,似乎可能会出现问题。例如,如果批量归一化训练到较大规模的训练输出,但同样的转移应用于较小的(由于有更多输出的补偿)规模数字而在测试期间没有丢失,那么班次可能已关闭。 TensorFlow 批量归一化层会自动对此进行补偿吗?或者这不是由于某种原因我失踪了吗?

另外,将这两者结合使用时,还有其他需要注意的陷阱吗?例如,假设我在上述方面以正确的顺序使用它们(假设 is 是正确的顺序),在多个连续层上同时使用批量标准化和 dropout 会不会有问题?我没有立即发现这有什么问题,但我可能会遗漏一些东西。

非常感谢!

更新:

一项实验测试似乎表明排序确实很重要。我只使用批处理规范和 dropout 反向运行了两次相同的网络。当 dropout 在批规范之前,验证损失似乎随着训练损失的下降而上升。在另一种情况下,它们都在下降。但在我的情况下,动作很慢,所以经过更多的训练后情况可能会发生变化,这只是一次测试。更明确和更明智的答案仍将不胜感激。

【问题讨论】:

【参考方案1】:

我阅读了答案中的推荐论文和来自的 cmets https://***.com/a/40295999/8625228

从 Ioffe 和 Szegedy (2015) 的角度来看,仅在 网络结构。李等人。 (2018) 给出统计和 实验分析表明,当 从业者在BN之前使用Dropout。因此,李等人。 (2018) 推荐 在所有 BN 层之后应用 Dropout。

从 Ioffe 和 Szegedy (2015) 的角度来看,BN 位于 内部/之前激活函数。然而,陈等人。 (2019) 使用结合了 dropout 和 BN 的 IC 层,Chen 等人。 (2019) 建议在 ReLU 之后使用 BN。

出于安全背景,我只在网络中使用 Dropout 或 BN。

陈光勇、陈鹏飞、史玉君、谢长玉、廖本本、 和张生宇。 2019.“重新思考批量标准化的使用 和深度神经网络训练中的辍学。” CorR 绝对/1905.05928。 http://arxiv.org/abs/1905.05928.

Ioffe、Sergey 和 Christian Szegedy。 2015.“批量标准化: 通过减少内部协变量加速深度网络训练 转移。” CoRR abs/1502.03167。 http://arxiv.org/abs/1502.03167.

李、向、陈硕、胡晓林和杨健。 2018.《理解 方差的辍学和批量标准化之间的不协调 转移。” CoRR abs/1801.05134。 http://arxiv.org/abs/1801.05134.

【讨论】:

【参考方案2】:

ConV/FC - BN - Sigmoid/tanh - 辍学。 如果激活函数是 Relu 或其他,规范化和 dropout 的顺序取决于您的任务

【讨论】:

【参考方案3】:

我发现一篇论文解释了 Dropout 和 Batch Norm(BN) 之间的不协调。关键思想就是他们所说的“方差转换”。这是因为 dropout 在训练和测试阶段具有不同的行为,这会改变 BN 学习的输入统计信息。 主要思想可以在这张来自paper 的图中找到。

这个效果的小演示可以在notebook找到。

【讨论】:

这如何回答这个问题? 本文提供了 2 种潜在策略: - 在所有 BN 层之后应用 Dropout(仅) - 将 Dropout 更改为方差更稳定的形式 @nbubis 我认为它间接回答了它。似乎建议不要一起使用它们(“解释了 Dropout 和 Batch Norm(BN) 之间的不和谐”)。【参考方案4】:

Conv - Activation - DropOut - BatchNorm - Pool --> Test_loss: 0.04261355847120285

Conv - Activation - DropOut - Pool - BatchNorm --> Test_loss:0.050065308809280396

Conv - Activation - BatchNorm - Pool - DropOut --> Test_loss:0.04911309853196144

Conv - Activation - BatchNorm - DropOut - Pool --> Test_loss:0.06809622049331665

Conv - BatchNorm - Activation - DropOut - Pool --> Test_loss:0.038886815309524536

Conv - BatchNorm - Activation - Pool - DropOut --> Test_loss: 0.04126095026731491

Conv - BatchNorm - DropOut - Activation - Pool --> Test_loss:0.05142546817660332

Conv - DropOut - Activation - BatchNorm - Pool --> Test_loss: 0.04827788099646568

Conv - DropOut - Activation - Pool - BatchNorm --> Test_loss: 0.04722036048769951

Conv - DropOut - BatchNorm - Activation - Pool --> Test_loss:0.03238215297460556


使用 2 个卷积模块(见下文)在 MNIST 数据集(20 个 epoch)上进行训练,每次都使用

model.add(Flatten())
model.add(layers.Dense(512, activation="elu"))
model.add(layers.Dense(10, activation="softmax"))

卷积层的内核大小为(3,3),默认填充,激活为elu。 Pooling 是池边(2,2) 的 MaxPooling。损失为categorical_crossentropy,优化器为adam

对应的Dropout概率分别为0.20.3。特征图的数量分别为3264

编辑: 当我按照一些答案中的建议放弃 Dropout 时,它收敛得更快,但泛化能力比我使用 BatchNorm Dropout 时差。

【讨论】:

由于 NN 的随机性,仅玩一次训练是不够的。当您进行大约 100 次训练并取平均值时,结果会更准确。 这是对权重初始化的度量。 请预设随机种子并运行至少10次以上,否则一次训练的结果不可靠。 真正的问题不在于权重初始化(通常情况下,如果有足够的迭代次数,这没什么大不了的);而不是这种排序是否适用于 MNIST 以外的其他数据集【参考方案5】:

正确的顺序是:Conv > Normalization > Activation > Dropout > Pooling

【讨论】:

是否有任何来源支持这种说法?【参考方案6】:

基于research paper,为了获得更好的性能,我们应该在应用 Dropouts 之前使用 BN

【讨论】:

答案没有解决问题中提出的完整堆栈。【参考方案7】:

通常,只需删除 Dropout(当您有 BN 时):

“BN 在某些情况下消除了对 Dropout 的需求,因为 BN 在直观上提供了与 Dropout 类似的正则化优势” “ResNet、DenseNet 等架构不使用Dropout

更多详细信息,请参阅@Haramoz 在 cmets 中已经提到的这篇论文 [Understanding the Disharmony between Dropout and Batch Normalization by Variance Shift]。

【讨论】:

MLP 有什么用,将它们组合起来有用吗? @DINATAKLIT 当你真的没有足够的训练数据时,在我看来,是的。 @xtulo 你的意思是这个工作一旦他们是一个小的日期?就像我读过批量规范化在大型数据集上效果更好一样!我有点困惑:! @DINATAKLIT 在您之前的评论what about MLPs is it useful to combine them 中,您是说Is it useful to combine Dropout and BN when using MLPs 吗?我对此的感觉是,这主要取决于您的模型的大小和您拥有的训练数据量。 即使有BN,你仍然可以使用dropout。取决于设计。这是一项正在进行的研究。你可以看看这篇论文:arxiv.org/abs/1506.02142【参考方案8】:

正如 cmets 中所述,按层顺序阅读的惊人资源是 here。我已经浏览了 cmets,这是我在互联网上找到的最佳主题资源

我的 2 美分:

Dropout 旨在完全阻止来自某些神经元的信息,以确保神经元不会共同适应。 因此,批量标准化必须在 dropout 之后进行,否则您将通过标准化统计信息传递信息。

如果您考虑一下,在典型的机器学习问题中,这就是我们不计算整个数据的均值和标准差,然后将其拆分为训练集、测试集和验证集的原因。我们拆分然后计算训练集上的统计数据,并使用它们对验证和测试数据集进行归一化和居中

所以我建议方案 1(这需要考虑 pseudomarvin's 对已接受答案的评论)

-> CONV/FC -> ReLu(或其他激活)-> Dropout -> BatchNorm -> CONV/FC

相对于方案 2

-> CONV/FC -> BatchNorm -> ReLu(或其他激活)-> Dropout -> CONV/FC -> 在接受的答案中

请注意,这意味着与方案 1 下的网络相比,方案 2 下的网络应该显示过拟合,但 OP 运行了一些上面提到的测试并且它们支持方案 2

【讨论】:

关于 BatchNorm 放置的相关 reddit 讨论:reddit.com/r/MachineLearning/comments/67gonq/… 但这不会搞砸您的 BN 统计数据,因为您将在应用 dropout 后计算它们,而在测试时不会出现这种情况? @ZakJ 我猜不是。因为我们计算每个单元的 BN(针对每个内部特征),而且它会被缩放以补偿 dropout。 @ZakJ 是正确的。在此处查看 mohammed adel 的回答和本文:arxiv.org/pdf/1801.05134.pdf。实际上,Batch Normalization 层学会了抵消在测试时关闭 Dropout 时不再存在的数据中的协变量偏移。 @skeller88 我还没有读过这篇论文。在我的脑海中,我认为如果你在 dropout 之前有 BN,那么这基本上会破坏 BN 层的意图,因为 BN 的功能是为下一层提供标准化数据。【参考方案9】:

在Ioffe and Szegedy 2015 中,作者声明“我们希望确保对于任何参数值,网络始终产生具有所需分布的激活”。因此,批标准化层实际上是在 Conv 层/全连接层之后插入的,但在输入 ReLu(或任何其他类型的)激活之前。请在大约 53 分钟的时间查看 this video 了解更多详情。

就 dropout 而言,我相信 dropout 是在激活层之后应用的。在dropout paper 图 3b 中,隐藏层 l 的 dropout 因子/概率矩阵 r(l) 应用于 y(l) 上,其中 y(l) 是应用激活函数 f 后的结果。

所以总结一下,使用batch normalization和dropout的顺序是:

-> CONV/FC -> BatchNorm -> ReLu(或其他激活) -> Dropout -> CONV/FC ->

【讨论】:

现在似乎连 Christian Szegedy 都喜欢在 ReLU 之后(而不是在它之前)执行 BatchNorm。引用 Keras 的作者 F. Chollet 的话:“我还没有回去检查他们在原始论文中的建议,但我可以保证 Christian 最近编写的代码在 BN 之前应用了 relu。它仍然偶尔会成为一个话题不过,辩论。” source 池化怎么样,会在批处理规范和激活之间进行吗? 另外,看起来激活后使用 BN 的准确性可能更高:github.com/cvjena/cnn-models/issues/3 视频被莫名其妙地删除了! This paper 表明,BN 通常会导致更差的结果,除非进行一些调节以避免方差变化的风险。

以上是关于批量标准化和辍学的顺序?的主要内容,如果未能解决你的问题,请参考以下文章

cifar 10 的自动编码器,精度低

测试期间的批量标准化

Keras:使用批量标准化在同一数据集上的不同训练和验证结果

张量流中推理时的批量标准化

添加批量标准化会降低性能

批量标准化[关闭]