You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TensorFlow加载ResNet模型权重后测试结果异常波动问题排查

问题描述

我在TensorFlow中实现并训练了一个ResNet模型,通过以下方式保存模型:

save_path=saver.save(sess,"/home/.../model.ckpt",global_step=50)
saver.save(sess,"/home/s.../model.ckpt",global_step=50)

在另一个脚本中,我尝试加载该模型并在一些图片上测试,脚本结构如下:

files = [s for s in os.listdir(dossier_source+'/'+d) if s.endswith(".png") or(".jpeg")]
print files.__len__()
batch_size_arg=files.__len__()
x = tf.placeholder(tf.float32, [None,IMAGE_WIDTH,IMAGE_HEIGHT,NUMBER_OF_CHANNELS], name='x-input')
y = tf.placeholder(tf.int32, [None], name='y-input')
train_file =str(dossier_source+d+"/*.png")

# 我重建了所有变量[...]
with tf.Session() as sess:
    sess.run(tf.local_variables_initializer())
    saver=tf.train.Saver()
    saver.restore(sess,tf.train.latest_checkpoint(global_path))
    tab= sess.run('conv0/conv:0')
    print tab[0][0][0] # 此测试证明conv0权重与训练时一致
    for i in xrange(1):
        im_batch, lab_batch = sess.run([images_batch, labels_batch])
        curr=sess.run(accuracy,feed_dict={x: im_batch, y: lab_batch})
        top=sess.run(top_k_op ,feed_dict={x: im_batch, y: lab_batch})
        conf =sess.run(confusion,feed_dict={x: im_batch, y: lab_batch, })
        print "Results"
        print curr
        print conf

我的问题是:尽管conv0权重每次都一致,但同一批图片测试时混淆矩阵和结果却每次不同……我在加载权重和模型时是否操作有误?

编辑:最新测试发现,即使执行以下循环测试同一批3张图片,结果也不同:

for i in xrange(3):
    im_batch, lab_batch = sess.run([images_batch, labels_batch])
    curr=sess.run(accuracy,feed_dict={x: im_batch, y: lab_batch})
    top=sess.run(top_k_op ,feed_dict={x: im_batch, y: lab_batch})
    conf =sess.run(confusion,feed_dict={x: im_batch, y: lab_batch, })
    print "Results"
    print curr
    print conf

问题排查与解决思路

兄弟,权重没问题但结果随机,基本可以排除模型加载的问题——毕竟你已经验证了conv0的权重是对的。大概率是你的模型或者数据管道里还有没关闭的随机操作,我给你列几个最常见的原因和排查方向:

1. Dropout层没切换到测试模式

如果你的ResNet里用了Dropout,训练时会随机关掉一部分神经元来防止过拟合,但测试时必须把keep_prob设为1.0。要是你测试时还是用了训练时的keep_prob(比如0.5),那每次前向传播都会随机失活不同的神经元,结果自然不一样。

检查一下测试时的feed_dict,有没有传入keep_prob: 1.0,或者模型里的Dropout层参数是不是固定死了训练模式?

2. Batch Normalization(BN层)没切换到测试模式

BN层在训练和测试时的逻辑完全不一样:训练时用当前batch的均值和方差,测试时要用训练阶段累积的滑动均值和方差。要是你测试时没把BN层的is_training设为False,那每次测试都会重新计算当前batch的均值方差,结果肯定会波动。

比如你用tf.layers.batch_normalization的话,构建模型时要传training这个占位符,测试时在feed_dict里传入training: False;要是用的是旧版的tf.contrib.layers.batch_norm,要确保测试时把is_training设为False。

3. 数据读取/预处理有随机操作

这个可能性也很大,你看你每次run(images_batch)得到的是不是真的同一批图片?

  • 如果用了tf.train.shuffle_batch这类带shuffle的读取操作,即使是同一数据集,每次run都会打乱顺序,要是你的batch size和数据集大小不一致,每次拿到的图片都不一样;就算batch size一致,顺序变了的话,混淆矩阵的行列对应也会乱(不过你说accuracy也变,那可能不是顺序问题)。
  • 另外,训练时加的数据增强操作(随机裁剪、翻转、亮度调整这些),测试时必须关掉!要是测试时还在随机增强,每张图片每次读进来都不一样,结果肯定波动。

先把数据预处理里的所有随机操作都注释掉,把数据读取的shuffle改成False,再跑一遍测试,看看结果是不是一致了。

4. 局部变量初始化的小坑

你测试时只跑了sess.run(tf.local_variables_initializer()),虽然你restore了模型,但有些局部变量(比如BN层的滑动均值方差)如果没被包含在saver的变量列表里,初始化后会变成随机值?不过你已经验证了conv0权重是对的,这个可能性相对小,但可以试试把初始化步骤放在restore之后?或者检查一下saver是不是包含了所有需要的变量(比如用tf.global_variables()来创建saver,确保覆盖所有可训练变量)。

快速验证方法:固定随机种子

在脚本开头加上:

import numpy as np
np.random.seed(123)
tf.set_random_seed(123)

如果结果变得完全一致,那百分百是某个随机操作没控制住,再回头按上面的方向排查就行。


内容的提问来源于stack exchange,提问作者Ho Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:57:22