Keras(TF 后端)中的 BatchNormalization 实现 - 激活之前还是之后?
Posted
技术标签:
【中文标题】Keras(TF 后端)中的 BatchNormalization 实现 - 激活之前还是之后?【英文标题】:BatchNormalization Implementation in Keras (TF backend) - Before or After Activation? 【发布时间】:2019-09-13 14:37:54 【问题描述】:考虑下面的代码sn-p
model = models.Sequential()
model.add(layers.Dense(256, activation='relu')) # Layer 1
model.add(BatchNormalization())
model.add(layers.Dense(128, activation='relu')) # Layer 2
我正在使用带有 Tensorflow 后端的 Keras。
我的问题是 - 在 Keras 的实现中,BN 是在激活函数之前还是之后执行的?
为了更加清晰,
BN 应该在激活之前还是之后应用尚有争议,最初的 (Ioffe and Szegedy 2015) 论文建议“BEFORE”,但来自以下线程的 cmets 显示了不同的意见。 Ordering of batch normalization and dropout?
在 Keras 文档 (https://keras.io/layers/normalization/) 中,它说 “在每批中标准化前一层的激活,即应用保持平均激活接近 0 和激活标准偏差接近 1 的变换。”
Keras 的文档似乎建议 BN 在激活后应用(即在上面的示例代码中,BN 在第 1 层的“relu”之后应用)。我想确认一下是不是这样?
另外,是否可以配置在激活函数之前或之后应用BN?
谢谢!
【问题讨论】:
【参考方案1】:除了原论文在激活前使用批量归一化外,Bengio 的书Deep Learning, section 8.7.1 给出了为什么在激活之后(或直接在输入到下一层之前)应用批量归一化可能会导致一些问题的原因:
很自然地想知道我们是否应该将批量标准化应用于 输入 X,或转换后的值 XW+b。约夫和塞格迪 (2015) 推荐后者。更具体地说,XW+b 应该被替换为 XW 的标准化版本。应该省略偏置项,因为它 随着批次应用的 β 参数变得多余 归一化重新参数化。层的输入通常是 非线性激活函数的输出,例如修正后的线性 在前一层中起作用。输入的统计数据因此是 更非高斯且更不易通过线性标准化 操作。
换句话说,如果我们使用 relu 激活,所有负值都映射为零。这可能会导致平均值已经非常接近于零,但剩余数据的分布将严重向右倾斜。试图将数据归一化为漂亮的钟形曲线可能不会给出最好的结果。对于 relu 系列之外的激活,这可能不是什么大问题。
有些报告在激活后进行批量标准化时效果更好,而另一些则在激活前进行批量标准化时得到更好的结果。最好使用这两种配置来测试您的模型,如果激活后的批量标准化显着降低了验证损失,请改用该配置。
【讨论】:
【参考方案2】:在activation
之后或之前添加BatchNorm
仍然是一个公开辩论。作者建议的原始版本运行良好,并已在许多实现中使用。但是很多人发现激活后的BN确实效果很好,有助于更快的收敛。例如,查看this 线程中的讨论。
简而言之,这取决于任务!哪一个会表现得更好?你必须自己检查一下。是的,您可以控制订单。例如:
x = Conv2D(64, (3,3), activation=None)(inputs)
x = BatchNormalization()(x)
x = Activation("relu")(x)
或
x = Conv2D(64, (3,3), activation="relu")(inputs)
x = BatchNormalization()(x)
【讨论】:
以上是关于Keras(TF 后端)中的 BatchNormalization 实现 - 激活之前还是之后?的主要内容,如果未能解决你的问题,请参考以下文章
Keras 2.3.0 发布:支持TensorFlow 2.0!!!!!
Tensorflow 与 Keras 中的 RNN,tf.nn.dynamic_rnn() 的贬值