该报错本质是变量名不匹配,而非缺失变量;主因是保存与加载时saver的var_list不一致,或模型定义中作用域/name_scope变更导致变量命名差异,需用NewCheckpointReader比对实际保存键与当前变量名。

“Key Variable_xxx not found in checkpoint” 是变量名不匹配,不是真的“缺变量”
这个报错表面是“找不到变量”,实际绝大多数情况是 saver.restore() 试图加载的变量名集合,和 checkpoint 文件里存的变量名对不上。常见原因有两个:一是保存时用了 var_list 过滤,但加载时没用同一批变量;二是模型定义顺序/作用域变了,导致变量名自动重命名(比如加了新层、改了 name_scope)。最直接的验证方式是用 pywrap_tensorflow.NewCheckpointReader 看真实存了哪些键:
from tensorflow.python import pywrap_tensorflow
reader = pywrap_tensorflow.NewCheckpointReader("./model.ckpt")
for key in reader.get_variable_to_shape_map():
print("saved:", key)
再对比你代码里 tf.trainable_variables() 或 tf.global_variables() 输出的变量名——只要不一致,就必然报这个错。
trainable=True 不等于“会被 saver 保存”,得看 saver 构造时传了谁
tf.Variable(..., trainable=True) 只影响它是否进 tf.trainable_variables() 列表,跟 tf.train.Saver 保存范围完全无关。Saver 默认保存 tf.global_variables(),但如果你显式传了 var_list,它就只认那个列表。
- 保存时用了
saver = tf.train.Saver(var_list=tf.trainable_variables())→ checkpoint 里只有可训练变量 - 加载时却用默认
saver = tf.train.Saver()→ 它会去找所有全局变量,自然报 “Key not found” - 反过来也一样:保存时没限制,加载时却指定
var_list=tf.trainable_variables(),也会漏掉moving_mean、moving_variance这类不可训练但被保存的 BN 参数
所以保存和加载的 var_list 必须严格一致,不能凭感觉猜。
立即学习“Python免费学习笔记(深入)”;
TensorFlow 1.x 和 2.x 的变量管理逻辑完全不同
TensorFlow 1.x 依赖显式图构建和 Variable 命名空间,变量名由 name_scope + variable_scope + 变量名拼成;而 TensorFlow 2.x 默认 Eager 模式,tf.train.Checkpoint 靠对象引用关系保存,不依赖字符串匹配。
- 1.x 场景下,哪怕只是多调了一次
tf.variable_scope("xxx"),变量名就可能从"dense/kernel:0"变成"xxx/dense/kernel:0" - 2.x 用
tf.train.Checkpoint(model=model)保存,加载时只要模型结构一致、对象层级相同,名字对不上也能恢复成功 - 混用 1.x 的
Saver加载 2.x 的 checkpoint 文件,或反过来,100% 报错
查错前先确认你用的是哪个版本的保存/加载机制,别拿 Checkpoint.restore() 去加载一个 .ckpt.index 文件。
用 trainable 属性检查变量状态,但别把它当保存开关
tf.trainable_variables() 是个调试利器,但它只反映当前图中“标记为可训练”的变量,不能替代对 checkpoint 内容的直接检查。
- 运行
print([v.name for v in tf.trainable_variables()]),和reader.get_variable_to_shape_map().keys()对比,能快速定位漏存或误存 - BN 层的
moving_mean、moving_variance默认trainable=False,但必须保存才能保证推理一致性;如果只保存trainable_variables(),这些参数就丢了 - 自定义层里手动创建的
tf.Variable(..., trainable=False),若没被Checkpoint或Saver显式包含,就不会进 checkpoint
真正决定“有没有被保存”的,永远是 saver 构造时的 var_list 或 Checkpoint 初始化时传入的对象,不是变量自身的 trainable 属性值。


















