首页 > 解决方案 > tf.keras.BatchNormalization 给出意外的输出

问题描述

import tensorflow as tf
tf.enable_eager_execution()

print(tf.keras.layers.BatchNormalization()(tf.convert_to_tensor([[5.0, 70.0], [5.0, 60.0]])))
print(tf.contrib.layers.batch_norm(tf.convert_to_tensor([[5.0, 70.0], [5.0, 60.0]])))"

上述代码的输出(在 Tensorflow 1.15 中)是:

tf.Tensor([[ 4.99 69.96] [ 4.99 59.97]], shape=(2, 2), dtype=float32)
tf.Tensor([[ 0. 0.99998] [ 0. -0.99998]], shape=(2, 2), dtype=float32)

我的问题是为什么同一个函数给出完全不同的输出。我也玩了一些函数的参数,但结果是一样的。对我来说,第二个输出是我想要的。此外,pytorch 的 batchnorm 也提供与第二个相同的输出。所以我认为这是keras的问题。

知道如何在 keras 中修复 batchnorm 吗?

标签: pythontensorflowkerasbatch-normalization

解决方案


Batch Normalization 层在训练和推理中具有不同的行为:

  1. 在训练期间(即使用 fit() 或使用参数 training=True 调用层/模型时),层使用当前批次输入的均值和标准差对其输出进行归一化。

  2. 在推理过程中(即使用 evaluate() 或 predict() 或使用参数 training=False (这是默认值)调用层/模型时,层使用均值和标准差的移动平均值对其输出进行归一化它在训练期间看到的批次。

因此,第一个结果是由于 defaulttraining=False而第二个是由于 default is_training=True

如果您想要相同的结果,您可以尝试:

x = tf.convert_to_tensor([[5.0, 70.0], [5.0, 60.0]])
print(tf.keras.layers.BatchNormalization()(x, training=True).numpy().tolist())
print(tf.contrib.layers.batch_norm(x).numpy().tolist())
#output
#[[0.0, 0.9999799728393555], [0.0, -0.9999799728393555]]
#[[0.0, 0.9999799728393555], [0.0, -0.9999799728393555]]

或者

x = tf.convert_to_tensor([[5.0, 70.0], [5.0, 60.0]])
print(tf.keras.layers.BatchNormalization()(x).numpy().tolist())
print(tf.contrib.layers.batch_norm(x, is_training=False).numpy().tolist())
#output
#[[4.997501850128174, 69.96502685546875], [4.997501850128174, 59.97002410888672]]
#[[4.997501850128174, 69.96502685546875], [4.997501850128174, 59.97002410888672]]

推荐阅读