在哪里对标准 CNN 应用批量归一化

Posted

技术标签:

【中文标题】在哪里对标准 CNN 应用批量归一化【英文标题】:Where to apply batch normalization on standard CNNs 【发布时间】:2018-04-19 00:06:05 【问题描述】:

我有以下架构:

Conv1
Relu1
Pooling1
Conv2
Relu2
Pooling3
FullyConnect1
FullyConnect2

我的问题是,我在哪里应用批量标准化?在 TensorFlow 中执行此操作的最佳功能是什么?

【问题讨论】:

【参考方案1】:

原来的batch-norm paper 规定在激活 ReLU 之前使用批处理规范。但有证据表明,在激活之后 使用 batchnorm 可能会更好。这是 Francois Chollet 对 Keras GitHub 的评论:

...我可以保证 Christian [Szegedy] 最近编写的代码 应用relu 在国阵之前。不过,它仍然偶尔会成为争论的话题。

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

【讨论】:

【参考方案2】:

关于这个问题有一些争论。 This Stack Overflow thread 和 this keras thread 是辩论的例子。 Andrew Ng 说批量归一化应该在当前层的非线性之前立即应用。 BN 论文的作者也说过,但是现在根据 keras 线程上的 François Chollet 的说法,BN 论文的作者在激活层之后使用了 BN。另一方面,the one discussed on this torch-residual-networks github issue 等一些基准表明 BN 在激活层之后表现更好。

我目前的观点(有待纠正)是你应该在激活层之后做 BN,如果你有预算并试图挤出额外的精度,那么在激活层之前尝试。

因此,将 Batch Normalization 添加到您的 CNN 将如下所示:

Conv1
Relu1
BatchNormalization
Pooling1
Conv2
Relu2
BatchNormalization
Pooling3
FullyConnect1
BatchNormalization
FullyConnect2
BatchNormalization

【讨论】:

可能差别不大,但池化后的归一化可能会快一点。【参考方案3】:

除了原论文在激活前使用批量归一化外,Bengio 的书Deep Learning, section 8.7.1 给出了为什么在激活之后(或直接在输入到下一层之前)应用批量归一化可能会导致一些问题的原因:

很自然地想知道我们是否应该将批量标准化应用于 输入 X,或转换后的值 XW+b。约夫和塞格迪 (2015) 推荐后者。更具体地说,XW+b 应该被替换为 XW 的标准化版本。应该省略偏置项,因为它 随着批次应用的 β 参数变得多余 归一化重新参数化。层的输入通常是 非线性激活函数的输出,例如修正后的线性 在前一层中起作用。输入的统计数据因此是 更非高斯且更不易通过线性标准化 操作。

换句话说,如果我们使用 relu 激活,所有负值都映射为零。这可能会导致平均值已经非常接近于零,但剩余数据的分布将严重向右倾斜。试图将数据归一化为漂亮的钟形曲线可能不会给出最好的结果。对于 relu 系列之外的激活,这可能不是什么大问题。

有些报告在激活后进行批量归一化时效果更好,而另一些则在激活之前进行批量归一化得到更好的结果。这是一场公开辩论。我建议您使用这两种配置来测试您的模型,如果激活后的批量标准化显着降低了验证损失,请改用该配置。

【讨论】:

以上是关于在哪里对标准 CNN 应用批量归一化的主要内容,如果未能解决你的问题,请参考以下文章

[Python] 数组归一化

Batch Normalization:批量归一化

「深度学习一遍过」必修12:激活函数池化归一化泛化正则化

归一化和标准化的差别在哪里?

4-16 归一化,抽象类,接口类,多态

批归一化(Batch Normalization)