【问题标题】:Getting low test accuracy using Tensorflow batch_norm function使用 Tensorflow batch_norm 函数获得低测试精度
【发布时间】:2017-02-26 03:51:03
【问题描述】:

我在 MNIST 数据上使用 Tensorflow 的官方批量标准化 (BN) 函数 (tf.contrib.layers.batch_norm())。我使用以下代码添加 BN:

local4_bn = tf.contrib.layers.batch_norm(local4, is_training=True)

在测试期间,我在上面的代码行中更改了“is_training=False”,并观察到只有 20% 的准确率。但是,如果我将上述代码也用于批量大小为 100 个图像的测试(即保持 is_training=True),它会提供 ~99% 的准确度。这个观察表明batch_norm() 计算的指数移动平均和方差可能不正确,或者我的代码中遗漏了一些东西。

谁能回答一下上述问题的解决方法。

【问题讨论】:

    标签: python tensorflow


    【解决方案1】:

    当您使用 is_training=True 测试您的模型时,您的准确率约为 99%,这仅仅是因为批量大小为 100。 如果您将批量大小更改为 1,您的准确度将会降低。

    这是因为您正在计算输入批次的指数移动平均值和方差,而不是使用这些值对层输出进行(批次)标准化。

    batch_norm 函数具有参数variables_collections,可帮助您在训练阶段存储计算的移动平均值和方差,并在测试阶段重复使用它们。

    如果您为这些变量定义了一个集合,那么batch_norm 层将在测试阶段使用它们,而不是计算新值。

    因此,如果您将批量标准化层定义更改为

    local4_bn = tf.contrib.layers.batch_norm(local4, is_training=True, variables_collections=["batch_norm_non_trainable_variables_collection"])
    

    层会将计算的变量存储到"batch_norm_non_trainable_variables_collection" 集合中。

    在测试阶段,当您传递is_training=False 参数时,层将重新使用它在集合中找到的计算值。

    请注意,移动平均值和方差不是可训练参数,因此,如果您仅将模型可训练参数保存在检查点文件中,则必须手动将存储的不可训练变量添加到先前定义的集合中。

    您可以在创建Saver 对象时执行此操作:

    saver = tf.train.Saver(tf.get_trainable_variables() + tf.get_collection_ref("batch_norm_non_trainable_variables_co‌​llection") + otherlistofvariables)
    

    另外,由于批量归一化会限制应用层的表达能力(因为它限制了值的范围),你应该让网络学习参数gammabetapaper 中描述的仿射变换系数)允许网络学习,因此,仿射变换增加了层的表示能力。

    您可以将这些参数的学习设置为Truebatch_norm函数的参数,这样:

    local4_bn = tf.contrib.layers.batch_norm(
        local4,
        is_training=True,
        center=True, # beta
        scale=True, # gamma
        variables_collections=["batch_norm_non_trainable_variables_collection"])
    

    【讨论】:

    • 非常感谢。我正在使用命令保存文件: saver.save(sess, checkpoint_path, global_step=step) 我看不到使用 save() 保存不可训练参数的任何选项。你能告诉我如何保存和恢复不可训练的参数吗?
    • 创建保存器时,您可以指定要保存的变量。 saver = tf.train.Saver(tf.get_trainable_variables() + tf.get_collection_ref("batch_norm_non_trainable_variables_collection") + otherlistofvariables)
    • 我遵循了解决方案(添加了 variable_collection 并保存了不可训练的参数),但仍然观察到同样的问题。但是,我使用了 this 的 batch_norm_wrapper() 函数,尽管我没有明确保存不可训练的参数,但它在训练和测试中都能完美运行。
    • 我不知道。 here 我定义了一个包含 tf.contrib.layers.batch_norm 方法的 batch_norm 层,我使用它(在父目录的 train.py 文件中),正如我告诉你的那样,它起作用了。也许你可以看看我的源代码,找出你和我的实现之间的区别
    • 感谢 @nessuno 分享您的代码,这最终帮助我找到了缺失的元素。需要加scale=True才能解决问题。在您的代码中,scale 的默认值是 True,而在原始代码中它被设置为 false。此外,我认为我应该设置updates_collections=None 用于就地更新参数。对于保存问题,我认为默认保护程序tf.train.Saver() 保存所有(可训练和不可训练)变量。
    【解决方案2】:

    我在处理 MNIST 时遇到了同样的问题。我的train acc是正常的,而test acc一开始很低,后来慢慢变大了。

    我将默认动量 = 0.99 更改为动量 = 0.9,然后它工作正常 我的源代码在这里:

    mnist_bn_fixed.py

    【讨论】:

      猜你喜欢
      • 2017-09-20
      • 2020-12-17
      • 1970-01-01
      • 2020-06-04
      • 1970-01-01
      • 2018-07-07
      • 1970-01-01
      • 2017-07-23
      • 2017-08-03
      相关资源
      最近更新 更多