【问题标题】:Why batch_normalization in tensorflow does not give expected results?为什么 tensorflow 中的 batch_normalization 没有给出预期的结果?
【发布时间】:2018-06-04 21:51:25
【问题描述】:

我想在一个小例子中看到 batch_normalization 层的输出,但显然我做错了什么,所以我得到了与输入相同的输出。

import tensorflow as tf
import keras.backend as K
K.set_image_data_format('channels_last')

X = tf.placeholder(tf.float32,  shape=(None, 2, 2, 3))  #  samples are 2X2 images with 3 channels
outp =  tf.layers.batch_normalization(inputs=X,  axis=3)

x = np.random.rand(4, 2, 2, 3)  # sample set: 4 images

init_op = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init_op)
    K.set_session(sess)
    a = sess.run(outp, feed_dict={X:x, K.learning_phase(): 0})
    print(a-x) # print the difference between input and normalized output

上述代码的输入和输出几乎相同。谁能给我指出问题?

【问题讨论】:

    标签: tensorflow neural-network conv-neural-network batch-normalization


    【解决方案1】:

    请记住,batch_normalization 在训练和测试时的行为不同。在这里,您从未“训练”过批量归一化,因此它学习的移动平均值是随机的但接近 0,移动方差因子接近 1,因此输出与输入几乎相同。如果您使用K.learning_phase(): 1,您将已经看到一些差异(因为它会使用批次的平均值和标准偏差进行归一化);如果您首先学习大量示例,然后在其他一些示例上进行测试,您还会看到发生了归一化,因为学习的均值和标准差不会是 0 和 1。

    为了更好地了解批量标准化的效果,我还建议您将输入乘以一个大数字(例如 100),以便您在未标准化和标准化向量之间有明显的区别,这将帮助您测试什么是继续。

    编辑:在您的代码中,移动均值和移动方差的更新似乎从未完成。您需要确保更新操作已运行,如 batch_normalization's doc 中所示。以下几行应该使它工作:

    outp =  tf.layers.batch_normalization(inputs=X,  axis=3, training=is_training, center=False, scale=False)
    
    update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
    with tf.control_dependencies(update_ops):
        outp = tf.identity(outp)
    

    下面是我的完整工作代码(我去掉了 Keras,因为我不太了解它,但你应该可以重新添加它)。

    import tensorflow as tf
    import numpy as np
    
    X = tf.placeholder(tf.float32,  shape=(None, 2, 2, 3))  #  samples are 2X2 images with 3 channels
    is_training = tf.placeholder(tf.bool,  shape=())  #  samples are 2X2 images with 3 channels
    outp =  tf.layers.batch_normalization(inputs=X,  axis=3, training=is_training, center=False, scale=False)
    
    update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
    with tf.control_dependencies(update_ops):
        outp = tf.identity(outp)
    
    x = np.random.rand(4, 2, 2, 3) * 100  # sample set: 4 images
    
    init_op = tf.global_variables_initializer()
    with tf.Session() as sess:
        sess.run(init_op)
        initial = sess.run(outp, feed_dict={X:x, is_training: False})
        for i in range(10000):
            a = sess.run(outp, feed_dict={X:x, is_training: True})
            if (i % 1000 == 0):
                print("Step %i: " %i, a-x) # print the difference between input and normalized output
    
        final = sess.run(outp, feed_dict={X: x, is_training: False})
        print("initial: ", initial)
        print("final: ", final)
        assert not np.array_equal(initial, final)
    

    【讨论】:

    • 但是如果 beta 和 gamma(学习到的均值和标准)不是 0 和 1,那么只有样本的均值和标准是有效的吗?这让我期望看到我的输出发生相当大的变化。
    • 另外,在使用 k.learning_phase(): 1 的学习阶段后,使用更大的数据集,我看不出有任何区别。
    • 查看我的编辑:更新从未运行,因此移动均值和方差保持不变。
    • 感谢编辑版本和完整示例。除了“更新操作”的问题外,我还注意到我们正在处理移动平均线,所以我们确实需要迭代以收敛到均值和标准。
    • 是的,这就是我想说的“先训练,后测试”,虽然不是很清楚
    猜你喜欢
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多