2017-06-28 2 views
1

Lorsque j'essaie de comparer la sortie de variance de tf.nn.fused_batch_norm et celle de tf.nn.moments je n'ai pas les mêmes valeurs pour les mêmes entrées.La variance retournée par tf.nn.fused_batch_norm est différente de tf.nn.moments

import numpy as np 
import tensorflow as tf 
tf.reset_default_graph() 
inputs = tf.placeholder(shape=[None,4,4,1], dtype=tf.float32) 
mean1, var1 = tf.nn.moments(inputs, [0,1,2]) 
_, mean2, var2 = tf.nn.fused_batch_norm(\ 
       inputs, scale=[1.], offset=[0.], \ 
       mean=None, variance=None, epsilon=1e-5, \ 
       data_format='NHWC', is_training=True, \ 
       name='reference') 

val = np.random.rand(1,4,4,1) 
mean3 = tf.reduce_mean(inputs, [0, 1, 2]) 
mean_sq3 = tf.reduce_mean(tf.square(inputs), [0, 1, 2]) 
var3 = mean_sq3 - tf.square(mean3) 
var_eps1 = var3 + 1e-5 
var_eps2 = var3 + np.sqrt(1e-5) 
with tf.Session() as sess: 
    mean_val, var_val = sess.run([mean1, var1], {inputs:val}) 
    print "tf.nn.moments: mean:", mean_val, "| var:", var_val 
    mean_val, var_val = sess.run([mean2, var2], {inputs:val}) 
    print "tf.nn.fused_batch_norm: mean:", mean_val, "| var:", var_val 
    mean_val, var_val, var_eps1_val, var_eps2_val = sess.run([mean3, var3, var_eps1, var_eps2], {inputs:val}) 
    print "customs: mean:", mean_val, "| var:", var_val, "| var + eps:", var_eps1_val, "| var + sqrt(eps):", var_eps2_val 

Vous pouvez voir que j'essayé de vérifier si elle a quelque chose à voir avec epsilon, mais apparemment pas, comme le script a couru sur le retour de GPU ce (il est aléatoire, mais le problème se produit toujours):

tf.nn.moments: mean: [ 0.54445559] | var: [ 0.09011541] 
tf.nn.fused_batch_norm: mean: [ 0.54445559] | var: [ 0.09612311] 
customs: mean: [ 0.54445559] | var: [ 0.09011537] | var + eps: [ 0.09012537] | var + sqrt(eps): [ 0.09327765] 

Comme vous pouvez le voir la variance de tf.nn.fused_batch_norm est supérieure à celle de tf.nn.moments (même après avoir ajouté sqrt (epsilon))

Un indice pourquoi une telle différence? (Je ne pense pas> 5% est petit, et cela ne ressemble pas à un problème de précision numérique)

Répondre

4

tf.nn.moments est de calculer la variance d'échantillon, tandis que tf.nn.fused_batch_norm calcule l'estimateur de variance sans biais. La différence entre les deux est un facteur n/n-1, où n est la taille de votre échantillon. Le code appliquant ce facteur peut être trouvé here. Notez cependant que, bien que la variance renvoyée soit l'estimation non biaisée, la variance sauvegardée utilisée pour la moyenne mobile est la variance biaisée. Dans votre exemple, la taille de votre échantillon est 4*4*1=16 et vous remarquerez que var2 = var1 * 16/15.

Lorsque vous prenez un échantillon beaucoup plus grand, vous voyez que les différences entre var1 et var2 deviennent plus petites.

Cela vaut probablement la peine d'être mentionné dans la documentation.