我在MNIST数据上使用Tensorflow的官方批量归一化(BN)函数(tf.contrib.layers.batch_norm())。我使用以下代码添加BN:
local4_bn = tf.contrib.layers.batch_norm(local4, is_training=True)
在测试期间,我在上面的代码行中更改了“is_training = False”,并且只观察了20%的准确度。但是,如果我使用上述代码进行测试(即保持is_training = True),批量大小为100个图像,则可以提供约99%的准确度。这个观察结果表明batch_norm()计算的指数移动平均值和方差可能不正确,或者我的代码中缺少某些内容。
有谁可以回答有关上述问题的解决方案。
答案 0 :(得分:4)
当您使用is_training=True
测试模型时,由于批量大小为100,您可以获得~99%的准确度。
如果将批量大小更改为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_collection") + otherlistofvariables)
另外,由于批量规范化可以限制应用层的表达能力(因为它限制了值的范围),因此应该让网络学习参数gamma
和{{1 (paper中描述的仿射变换系数),允许网络学习,增加层的表示能力的仿射变换。
您可以通过以下方式启用这些参数的学习设置beta
True
功能的参数:
batch_norm
答案 1 :(得分:1)
我在处理MNIST时遇到了同样的问题。我的列车是正常的,而测试acc在开始时非常低,然后逐渐增长。
我将默认动量= 0.99更改为动量= 0.9,然后它工作正常 我的源代码在这里: