tf.layers.batch_normalization中"trainable"和"training"标志的意义

15
在tf.layers.batch_normalization中,“trainable”和“training”标志的重要性是什么?在训练和预测期间这两者有何不同?
3个回答

13

批量归一化有两个阶段:

1. Training:
   -  Normalize layer activations using `moving_avg`, `moving_var`, `beta` and `gamma` 
     (`training`* should be `True`.)
   -  update the `moving_avg` and `moving_var` statistics. 
     (`trainable` should be `True`)
2. Inference:
   -  Normalize layer activations using `beta` and `gamma`.
      (`training` should be `False`)

示例代码以说明几种情况:

#random image
img = np.random.randint(0,10,(2,2,4)).astype(np.float32)

# batch norm params initialized
beta = np.ones((4)).astype(np.float32)*1 # all ones 
gamma = np.ones((4)).astype(np.float32)*2 # all twos
moving_mean = np.zeros((4)).astype(np.float32) # all zeros
moving_var = np.ones((4)).astype(np.float32) # all ones

#Placeholders for input image
_input = tf.placeholder(tf.float32, shape=(1,2,2,4), name='input')

#batch Norm
out = tf.layers.batch_normalization(
       _input,
       beta_initializer=tf.constant_initializer(beta),
       gamma_initializer=tf.constant_initializer(gamma),
       moving_mean_initializer=tf.constant_initializer(moving_mean),
       moving_variance_initializer=tf.constant_initializer(moving_var),
       training=False, trainable=False)


update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
init_op = tf.global_variables_initializer()

 ## 2. Run the graph in a session 

 with tf.Session() as sess:

    # init the variables   
    sess.run(init_op)

    for i in range(2):
        ops, o = sess.run([update_ops, out], feed_dict={_input: np.expand_dims(img, 0)})
        print('beta', sess.run('batch_normalization/beta:0'))
        print('gamma', sess.run('batch_normalization/gamma:0'))
        print('moving_avg',sess.run('batch_normalization/moving_mean:0'))
        print('moving_variance',sess.run('batch_normalization/moving_variance:0'))
        print('out', np.round(o))
        print('')

training=Falsetrainable=False 时:

  img = [[[4., 5., 9., 0.]...
  out = [[ 9. 11. 19.  1.]... 
  The activation is scaled/shifted using gamma and beta.

training=Truetrainable=False时:

  out = [[ 2.  2.  3. -1.] ...
  The activation is normalized using `moving_avg`, `moving_var`, `gamma` and `beta`. 
  The averages are not updated.

traning=Truetrainable=True时:

  The out is same as above, but the `moving_avg` and `moving_var` gets updated to new values.

  moving_avg [0.03249997 0.03499997 0.06499994 0.02749997]
  moving_variance [1.0791667 1.1266665 1.0999999 1.0925]

谢谢@vijay m - Amit Gupta
在推理过程中,激活是否应该使用从训练中“学习”得到的移动平均值和方差进行归一化? - jul

5
这很复杂。在TF 2.0中,行为已经改变了,看看这个:

https://github.com/tensorflow/tensorflow/blob/095272a4dd259e8acd3bc18e9eb5225e7a4d7476/tensorflow/python/keras/layers/normalization_v2.py#L26


关于在BatchNormalization层上设置layer.trainable = False的含义: 设置layer.trainable = False的含义是冻结该层,即其内部状态在训练期间不会改变:其可训练权重在fit()或train_on_batch()期间不会更新,并且其状态更新也不会运行。通常,这并不一定意味着该层在推理模式下运行(通常由调用层时可以传递的training参数控制)。"冻结状态"和"推理模式"是两个独立的概念。 然而,在BatchNormalization层的情况下,设置trainable = False表示该层将随后以推理模式运行(这意味着它将使用移动平均值和移动方差来规范化当前批次,而不是使用当前批次的平均值和方差)。这种行为已经在TensorFlow 2.0中引入,以便使layer.trainable = False在卷积网络微调用例中产生最常见的预期行为。请注意: 此行为仅在TensorFlow 2.0及以上版本中发生。在1.*中,设置layer.trainable = False会冻结该层,但不会将其切换到推理模式。 在包含其他层的模型上设置trainable将递归地设置所有内部层的trainable值。 如果在对模型调用compile()之后更改trainable属性的值,则新值在此模型中不会生效,直到再次调用compile()。

3

training 控制是否使用训练模式的批量归一化(使用这个小批量的统计数据)还是推理模式的批量归一化(使用整个训练数据的平均统计数据)。trainable 控制批量归一化过程中创建的变量本身是否可训练。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接