【问题标题】:Why do batch_normalization produce all-zero output when training = True but produce non-zero output when training = False?为什么 batch_normalization 在训练 = True 时产生全零输出,但在训练 = False 时产生非零输出?
【发布时间】:2021-06-05 03:55:45
【问题描述】:

我正在关注 Tensorflow 教程 https://www.tensorflow.org/guide/migrate。这是一个例子:

def model(x, training, scope='model'):
  with v1.variable_scope(scope, reuse=v1.AUTO_REUSE):
    x = v1.layers.conv2d(x, 32, 3, activation=v1.nn.relu,
          kernel_regularizer=lambda x:0.004*tf.reduce_mean(x**2))
    x = v1.layers.max_pooling2d(x, (2, 2), 1)
    x = v1.layers.flatten(x)
    x = v1.layers.dropout(x, 0.1, training=training)
    x = v1.layers.dense(x, 64, activation=v1.nn.relu)
    x = v1.layers.batch_normalization(x, training=training)
    x = v1.layers.dense(x, 10)
    return x
train_data = tf.ones(shape=(1, 28, 28, 1))
test_data = tf.ones(shape=(1, 28, 28, 1))
train_out = model(train_data, training=True)
test_out = model(test_data, training=False)
print(train_out)
print(test_out)

training=True 所在的 train_out

tf.Tensor([[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]], shape=(1, 10), dtype=float32)

而 training=False 的 test_out 是随机的非零向量

tf.Tensor(
[[ 0.379358   -0.55901194  0.48704922  0.11619566  0.23902717  0.01691487
   0.07227738  0.14556988  0.2459927   0.2501198 ]], shape=(1, 10), dtype=float32)

看了https://www.tensorflow.org/api_docs/python/tf/keras/layers/BatchNormalization的文档,还是不明白为什么?救命!

【问题讨论】:

    标签: tensorflow batch-normalization


    【解决方案1】:

    为什么batch_normalization在训练时会产生全零输出= 是的

    这是因为您的批量大小 = 1。

    批量归一化层使用每个通道的批量均值和批量标准差对其输入进行归一化。

    当batch size为1且flatten后,每个channel中只有一个单值,所以batch mean(对于那个channel)本身就是单值,从而在batch normalization层之后输出一个零张量.

    但在训练时产生非零输出 = False?

    在推理过程中,批归一化层通过使用批均值和 SD 的移动平均值而不是当前批均值和 SD 来归一化输入。

    移动均值和SD分别初始化为零和一,并逐渐更新。因此,移动均值不等于开始时每个通道中的单个值,因此该层不会输出零张量。

    结论:使用批量大小 > 1 并输入具有随机值/实际数据值的张量,而不是所有元素都相同的 tf.ones()

    【讨论】:

    • 但是即使我删除了 dropout 层,training=False 的非零输出在每次运行期间都是随机变化的,我在代码中看不到随机因素?
    • 如果您“连续”运行 model(data,training=False),则不应更改输出。但是,如果在两个模型(数据,训练=假)调用之间有模型(数据,训练=真)调用,输出可能会不同,因为批均值和标准差的移动平均值将由训练=真调用更新。
    • 我发现随机性来自 conv2d 和两个密集层。我用 kernel_initializer=tf.ones_initializer() 设置了 3 层,然后消除了随机性。作为您的答案,training=True 时,batch_normalization 层的输出变为零,而 training=False 时,batch_normalization 层保持非零输出。在向它们输入真实数据之前,我想了解一些图层/操作的基本属性:)
    • 您是否有任何理由要使用那些已弃用的 API?刚刚发现它们每次都重新初始化变量(在def模型函数中)没有按预期工作,从而导致您遇到随机性问题。这些 API 不再受支持,我建议您使用 v2 keras api,它将正常工作。
    • 如果您是 tensorflow 新手,请遵循本指南:tensorflow.org/guide/keras/sequential_model。不要遵循可能具有误导性的迁移指南。
    猜你喜欢
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-14
    • 2020-05-06
    • 2015-10-02
    • 2013-02-13
    相关资源
    最近更新 更多