我有以下架构:
Conv1
Relu1
Pooling1
Conv2
Relu2
Pooling3
FullyConnect1
FullyConnect2
我的问题是,我在哪里应用批量标准化?在 TensorFlow 中执行此操作的最佳功能是什么?
我有以下架构:
Conv1
Relu1
Pooling1
Conv2
Relu2
Pooling3
FullyConnect1
FullyConnect2
我的问题是,我在哪里应用批量标准化?在 TensorFlow 中执行此操作的最佳功能是什么?
原始的批处理规范论文规定在 ReLU 激活之前使用批处理规范。但是有证据表明激活后使用 batchnorm 可能会更好。这是Francois Chollet在Keras GitHub 上的评论:
...我可以保证 Christian [Szegedy] 最近编写的代码在 BN 之前应用了 relu。不过,它仍然偶尔会成为争论的话题。
对于第二个问题:在 tensorflow 中,您可以使用高级tf.layers.batch_normalization
函数或低级tf.nn.batch_normalization
.
关于这个问题有一些争论。这个 Stack Overflow 线程和这个 keras 线程就是争论的例子。Andrew Ng 说,批量归一化应该在当前层的非线性之前立即应用。BN 论文的作者也说过,但是现在根据 keras 线程上的 François Chollet 的说法,BN 论文的作者在激活层之后使用了 BN。另一方面,有一些基准,例如在这个 torch-residual-networks github 问题上讨论的基准,表明 BN 在激活层之后表现更好。
我目前的观点(有待纠正)是你应该在激活层之后做 BN,如果你有预算并试图挤出额外的准确性,那么在激活层之前尝试。
因此,将 Batch Normalization 添加到您的 CNN 将如下所示:
Conv1
Relu1
BatchNormalization
Pooling1
Conv2
Relu2
BatchNormalization
Pooling3
FullyConnect1
BatchNormalization
FullyConnect2
BatchNormalization
除了在激活之前使用批量归一化的原始论文,Bengio 的书Deep Learning,第 8.7.1 节给出了为什么在激活之后(或直接在输入到下一层之前)应用批量归一化可能会导致一些问题的原因:
很自然地想知道我们是否应该对输入 X 或转换后的值 XW+b 应用批量归一化。Ioffe 和 Szegedy (2015) 推荐后者。更具体地说,XW+b 应该被 XW 的标准化版本替换。应该省略偏差项,因为它与批量归一化重新参数化应用的 β 参数变得多余。一层的输入通常是非线性激活函数的输出,例如前一层的修正线性函数。因此,输入的统计数据更加非高斯并且不太适合通过线性运算进行标准化。
换句话说,如果我们使用 relu 激活,所有负值都映射为零。这可能会导致平均值已经非常接近于零,但剩余数据的分布将严重向右倾斜。尝试将数据标准化为漂亮的钟形曲线可能不会给出最好的结果。对于 relu 系列之外的激活,这可能不是什么大问题。
有些人在激活后进行批量标准化时报告了更好的结果,而另一些人在激活前进行了批量标准化时获得了更好的结果。这是一场公开辩论。我建议您使用这两种配置来测试您的模型,如果激活后的批量标准化显着降低了验证损失,请改用该配置。