当您使用 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_collection") + otherlistofvariables)
另外,由于批量归一化会限制应用层的表达能力(因为它限制了值的范围),你应该让网络学习参数gamma和beta( paper 中描述的仿射变换系数)允许网络学习,因此,仿射变换增加了层的表示能力。
您可以将这些参数的学习设置为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"])