跨会话使用恢复的变量出现‘uninitialized value’错误
解决TensorFlow新会话中恢复图后变量未初始化的问题
这问题我之前也碰到过,本质是TensorFlow里计算图结构和变量值存储分离的机制导致的——你用meta_graph_def恢复的只是计算图的拓扑结构(比如各种操作、变量的定义),但变量的实际数值是存在会话的内存空间里的。第一个会话关闭后,这块内存就被系统回收了,新会话里虽然图结构完整,但变量还是处于未初始化的状态,自然会抛出FailedPreconditionError。至于调用sess.run(tf.global_variables_initializer())能“解决”报错,其实是给变量重新赋了初始值,直接覆盖了你之前恢复的结果,这显然不是你想要的解决方案。
正确的解决思路:同时保存并恢复图结构和变量值
要在新会话里复用之前的变量值,你需要同时保存图结构和变量的实际数值,然后在新会话中先加载图结构,再把变量值恢复到会话内存中。具体步骤如下:
1. 第一次保存时,同时存储图结构和变量值
在第一个会话完成变量训练/恢复后,用tf.train.Saver把两者都保存下来:
# 第一个会话中完成变量初始化/训练后 saver = tf.train.Saver() # 保存到指定路径,这会生成3个文件: # - my_model.meta:存储计算图结构 # - my_model.data-xxxx-of-xxxx:存储变量的实际数值 # - my_model.index:存储变量和数据文件的映射索引 saver.save(sess, './my_model')
2. 新会话中先加载图结构,再恢复变量值
新建会话后,先通过meta文件恢复图结构,再用checkpoint文件把变量值加载到当前会话的内存中:
with tf.Session() as new_sess: # 从meta文件导入计算图结构 saver = tf.train.import_meta_graph('./my_model.meta') # 从checkpoint文件恢复变量值(自动找最新的checkpoint) saver.restore(new_sess, tf.train.latest_checkpoint('./')) # 现在就可以正常使用图中的变量了,比如获取某个变量的值 graph = tf.get_default_graph() # 注意这里要使用变量的完整名称(保存时的名称,可通过graph.get_all_variables()查看) target_var = graph.get_tensor_by_name('your_variable_name:0') print(new_sess.run(target_var)) # 输出的是之前保存的变量值,而非初始值
几个需要注意的坑
- 如果之前只保存了meta图,没有保存变量值的checkpoint文件,那确实没办法恢复原来的变量值,只能重新训练或者找回之前的checkpoint文件。
- 恢复变量时,要确保新会话中的图结构和保存时完全一致(比如变量名称、操作名称不能随意修改),否则会出现找不到变量的错误。
- 不要混淆
tf.train.import_meta_graph和saver.restore的作用:前者负责加载图的拓扑结构,后者负责把变量的实际数值加载到当前会话的内存中,两者缺一不可。
内容的提问来源于stack exchange,提问作者Alex Rothberg
相关产品推荐
相关产品推荐

