代码之家  ›  专栏  ›  技术社区  ›  abaghb

为什么tensorflow中的batch\u规范化不能给出预期的结果?

  •  2
  • abaghb  · 技术社区  · 7 年前

    我希望在一个小示例中看到batch\u规范化层的输出,但显然我做错了什么,所以我得到了与输入相同的输出。

    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
    

    上述代码的输入和输出几乎相同。有人能给我指出这个问题吗?

    1 回复  |  直到 7 年前
        1
  •  2
  •   gdelab    7 年前

    记住这一点 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)