同一MNIST模型在当前与外部模块测试精度不一致问题排查
我刚踩过一模一样的坑!你遇到的这个精度差异问题,根源其实很隐蔽——train.py里初始化CNN模型时没有传入is_training参数,导致你测试时在feed_dict里设置is_training=False根本没起作用,模型里的BatchNorm、Dropout这类依赖训练/测试模式的层还停留在训练状态,自然精度比正确切换到测试模式的test.py要低。
问题核心对比
先看两段代码的关键差异:
- 在
train.py中初始化模型:y = cnn_model.CNN(x) # 这里漏掉了is_training参数! - 而
test.py中正确初始化模型:y = cnn_model.CNN(x, is_training=is_training) # 正确传入控制参数
你的CNN模型里肯定用到了Batch Normalization或者Dropout(不然不会有这么明显的精度差),这些层的行为完全由is_training开关控制:训练时要更新均值方差、启用dropout,测试时要固定均值方差、关闭dropout。但如果初始化模型时没把is_training参数传进去,后续再在feed_dict里传值也没用——模型计算图里根本没把这个占位符和层的行为绑定起来,相当于开关没接上,测试时还是按训练模式跑,所以精度掉了。
修复方案
把train.py里的模型初始化代码改成和test.py一致的写法(还要确保你已经在train.py里定义了is_training占位符):
# train.py中补充定义占位符并修改模型初始化 is_training = tf.placeholder(tf.bool, name='MODE') y = cnn_model.CNN(x, is_training=is_training)
修改后再在train.py里测试,精度就会和test.py一致了——因为现在模型能正确响应is_training=False的设置,切换到测试模式运行。
额外提醒
这种问题很容易被忽略,尤其是当模型结构封装在单独模块里的时候。记住:只要模型里有依赖训练/测试模式的层,初始化时一定要把控制模式的参数传进去,否则训练和测试的行为就会不一致,出现这种看似诡异的精度差异。
内容的提问来源于stack exchange,提问作者jasonKoolRay

