在标准CNN上应用批量归一化的位置在哪里?

17

我有以下架构:

Conv1
Relu1
Pooling1
Conv2
Relu2
Pooling3
FullyConnect1
FullyConnect2

我的问题是,在哪里应用批量归一化?在TensorFlow中,最好使用什么函数实现?

3个回答

14

原始的批量归一化论文建议在ReLU激活之前使用批量归一化。但是有证据表明,最好在激活使用批量归一化。以下是Francois Chollet在Keras GitHub上的评论:

...我可以保证由Christian [Szegedy]编写的最新代码应用了ReLU激活函数在BN之前。尽管如此,这仍然偶尔是一个争论的话题。

对于你的第二个问题:在tensorflow中,您可以使用高级tf.layers.batch_normalization函数或低级tf.nn.batch_normalization


13
这个问题存在一些争议。这个 Stack Overflow 线程这个 keras 线程 是争论的例子。Andrew Ng 表示批量归一化应该在当前层非线性之前立即应用。BN 论文的作者也这样说,但是现在根据 François Chollet 在 keras 线程上的说法,BN 论文的作者在激活层后使用 BN。另一方面,有一些基准测试,比如在这个 torch-residual-networks github 问题中讨论的那个,显示 BN 在激活层之后的表现更好。
我的目前观点(可修正)是应该在激活层之后进行 BN,如果你的预算充足并想要提高精度,则可以尝试在激活层之前进行 BN。
所以将 Batch Normalization 添加到您的 CNN 中会像这样:
Conv1
Relu1
BatchNormalization
Pooling1
Conv2
Relu2
BatchNormalization
Pooling3
FullyConnect1
BatchNormalization
FullyConnect2
BatchNormalization

3
这可能不会有太大的差别,但在池化后进行归一化可能会稍微快一些。 - Rémi

3
除了最初的论文在激活之前使用批量归一化外,Bengio的书《深度学习》第8.7.1节还提供了一些理由,说明为什么在激活后应用批量归一化(或直接在输入到下一层之前应用)可能会导致一些问题:
“自然而然地会想到我们是否应该将批量归一化应用于输入X还是变换后的值XW+b。Ioffe和Szegedy(2015)推荐后者。更具体地说,XW+b应该被XW的归一化版本所取代。偏置项应该被省略,因为它与批量归一化重新参数化所应用的β参数变得多余。一层的输入通常是非线性激活函数(如前一层中的修正线性函数)的输出。因此,输入的统计信息更不服从高斯分布,也不易通过线性操作进行标准化。”
换句话说,如果我们使用relu激活函数,所有负值都将被映射为零。这可能会导致平均值已经非常接近于零,但剩余数据的分布将严重偏向右侧。尝试将该数据归一化为一个漂亮的钟形曲线可能不会得到最好的结果。对于relu家族之外的激活函数,这可能不是一个很大的问题。
有些人报告在激活后放置批量归一化可以获得更好的结果,而另一些人则通过在激活之前进行批量归一化来获得更好的结果。这是一个开放性的辩论。我建议您使用两种配置测试您的模型,如果在激活后进行批量归一化可以显著降低验证损失,请使用该配置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接