最初的问题是关于TensorFlow具体实现的。但是,这些答案一般适用于实现。这个一般答案也是TensorFlow的正确答案。

当在TensorFlow中使用批处理归一化和dropout(特别是使用contrib.layers)时,我需要担心排序吗?

It seems possible that if I use dropout followed immediately by batch normalization there might be trouble. For example, if the shift in the batch normalization trains to the larger scale numbers of the training outputs, but then that same shift is applied to the smaller (due to the compensation for having more outputs) scale numbers without dropout during testing, then that shift may be off. Does the TensorFlow batch normalization layer automatically compensate for this? Or does this not happen for some reason I'm missing?

此外,在同时使用这两者时,还有其他需要注意的缺陷吗?例如,假设我以正确的顺序使用它们(假设有正确的顺序),在多个连续层上同时使用批处理规范化和dropout会有麻烦吗?我不认为这有什么问题,但我可能遗漏了一些东西。

非常感谢!

更新:

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


当前回答

在阅读了多个答案并进行了一些测试后,这些是我的假设

a)总是BN -> AC,(没有b/w他们)。 b) BN -> Dropout over Dropout -> BN,但两者都试一下。[最新研究发现第一名更好] c) BN消除了Dropout的需要,不需要使用Dropout。 d)最后共同完成。 e) Dropout前的BN为数据泄漏。 f)最好的办法是尝试每一种组合。


所谓最佳方法——

Layer -> BN -> AC -> Dropout -> Pool ->Layer

其他回答

我发现了一篇论文,解释了Dropout和Batch Norm(BN)之间的不和谐。关键思想是他们所谓的“方差偏移”。这是因为在训练和测试阶段之间,dropout有不同的行为,这改变了BN学习的输入统计数据。 主要思想可以从这张图中找到,这张图是从这篇论文中截取的。

这个效果的一个小演示可以在这个笔记本上找到。

基于研究论文,为了获得更好的性能,我们应该在应用Dropouts之前使用BN

转换激活- DropOut - BatchNorm - Pool——> Test_loss: 0.04261355847120285

转换激活- DropOut - Pool - BatchNorm——> Test_loss: 0.050065308809280396

转换激活- BatchNorm - Pool - DropOut——> Test_loss: 0.04911309853196144

转换激活- BatchNorm - DropOut - Pool——> Test_loss: 0.06809622049331665

转换- BatchNorm -激活- DropOut - Pool——> Test_loss: 0.038886815309524536

Conv - BatchNorm -激活- Pool - DropOut——> Test_loss: 0.04126095026731491

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

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

转换-退出-激活-池- 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.2或0.3。特征映射的数量分别为32或64。

编辑: 当我删除Dropout时,正如一些答案中推荐的那样,它收敛得更快,但泛化能力比我使用BatchNorm和Dropout时差。

在Ioffe和szgedy 2015中,作者指出:“我们希望确保对于任何参数值,网络总是以所需的分布产生激活”。因此,批处理归一化层实际上是在Conv层/全连接层之后插入的,但在进入ReLu(或任何其他类型)激活之前。请在53分钟左右观看这段视频了解更多细节。

至于dropout,我认为dropout应用于激活层之后。在dropout论文图3b中,将隐层l的dropout因子/概率矩阵r(l)应用于y(l)上,其中y(l)是应用激活函数f后的结果。

综上所述,使用批归一化和dropout的顺序为:

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

ConV/FC - BN - Sigmoid/tanh - dropout。 如果激活函数c是Relu或其他,归一化和退出的顺序取决于你的任务