tf.nn.fused_batch_norm返回的差异与tf.nn.moments不同

时间:2017-06-28 17:14:17

标签: tensorflow tensorflow-gpu

当我尝试比较来自tf.nn.fused_batch_norm的方差输出和来自tf.nn.moments的方差时,我对相同的输入没有相同的值。

$offset = ($catalog_index < 1) ? 0 : $goods_qty * $catalog_index + 1;
...
'offset' => $offset,

你可以看到我试图检查它是否与epsilon有关,但显然不是,因为脚本在GPU上运行返回此(它是随机的,但问题总是发生):

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

正如您所看到的,tf.nn.fused_batch_norm的差异高于tf.nn.moments(即使在添加sqrt(epsilon)之后)

有什么线索为何如此差异? (我认为&gt; 5%不小,看起来不像数值精度问题)

1 个答案:

答案 0 :(得分:4)

tf.nn.moments正在计算样本方差,而tf.nn.fused_batch_norm正在计算无偏差方差估计。两者之间的差异是因子n/n-1,其中n是您的样本数量。可以找到应用此因子的代码here

但请注意,虽然返回的方差是无偏估计值,但用于移动平均线的已保存的方差是有偏差的。

在您的示例中,您的样本大小为4*4*1=16,您会注意到var2 = var1 * 16/15

当你拍摄更大的样本时,你会发现var1var2之间的差异会变小。

在文档中可能值得一提。