笔者提交到gitHub上的问题描述地址是:https://github.com/tensorflow/tensorflow/issues/20140

三种持久化模型加载方式的一个小结论

加载持久化模型的三种方式:

第一,saver.restore:属于当前代码计算图已经定义,我需要将持久化模型中变量的值加载到当前代码计算图中的变量中去。所以,两者只能是持久化模型中的变量是当前代码计算图中变量集合的一个子集,必须是一种严格包含的关系。(当然,可以在初始化Saver的时候指定加载哪些变量)

第二,import_meta_graph则完全不允许当前代码计算图已经定义的变量节点和要加载的持久化模型中的节点存在冲突,因为它价值的是整个图。不是单纯将变量的值进行加载。

第三,使用pb文件的方式,即使持久化模型中的变量节点和当前代码计算图中定义的变量节点发生冲突,也是毛事没有,没有任何关系。因为pb文件的方式加载进来的计算图,

会全部加上import/前缀。也就是说,从命名空间上就隔开了这种冲突。

上述三点是很重要的结论,自己调试和观察的。

所以,使用别人的模型,最好的方式就是用pb文件。因为不会有冲突的可能!但是,有一个弊端就是,import命名空间下的变量不能参与到当前的训练!!!记住,不能参与训练!

问题描述(英文版):

write the code below, and save it to a ,ckpt as a model

import tensorflow as tf`
v1 = tf.Variable(tf.constant(1.0, shape=[]), name = "v1")
v2 = tf.Variable(tf.constant(2.0, shape=[]), name = "v2")
v3 = tf.Variable(tf.constant(3.0, shape=[]), name = "v3")
result=v1+v2
result2= result + v3 init_op = tf.global_variables_initializer()
saver = tf.train.Saver() with tf.Session() as sess:
sess.run(init_op)
writer = tf.summary.FileWriter('./graphs/const_add', sess.graph)
saver.save(sess, "Saved_model/model.ckpt")`

then in another .py, we restore the model from the model.ckpt file

import tensorflow as tf
saver = tf.train.import_meta_graph("Saved_model/model.ckpt.meta")
with tf.Session() as sess:
saver.restore(sess, "Saved_model/model.ckpt")
print (sess.run(tf.get_default_graph().get_tensor_by_name("add:0")))
#sess.run(tf.assign(v1,[10])) #直接这样使用v1,会提示v1没有定义 #with tf.variable_scope("",reuse=tf.AUTO_REUSE):
with tf.variable_scope("",reuse=False):
v1=tf.get_variable(name="v1",shape=[1])
print(v1.name)
sess.run(tf.assign(v1,[10]))
"""④输出所有可训练的变量名称,也就是神经网络的参数"""
trainable_variables=tf.trainable_variables()
variable_list_name = [c.name for c in tf.trainable_variables()]
variable_list = sess.run(variable_list_name)
for k,v in zip(variable_list_name,variable_list):
print("variable name:",k)
print("shape:",v.shape)
#print(v)
"""④输出所有可训练的变量名称,也就是神经网络的参数"""
print (sess.run(tf.get_default_graph().get_tensor_by_name("v1:0")))
print (sess.run(tf.get_default_graph().get_tensor_by_name("add:0")))
print (sess.run(tf.get_default_graph().get_tensor_by_name("add_1:0")))
print (sess.run(tf.get_default_graph().get_tensor_by_name("v1_1:0")))

the results will be as below:

we will find that:
if we restore some variables from the already existed model file ""Saved_model/model.ckpt.meta")",
such as v1,v2,v3 in this example.
it will influence the process of calling get_variable. Because of these two causes as below:

  1. the variables restored from the model file such as v1,v2 and v3 will not exist in the scope of get_variable, it means you can only use
with tf.variable_scope("",reuse=False):
v1=tf.get_variable(name="v1",shape=[1])

and create a new variable. you can not reuse the restored variable v1 from the model file unless you define a v1 , before you restore from the model file. like below

v1=tf.get_variable(name="v1",shape=[1])
saver = tf.train.Saver()
with tf.Session() as sess:
saver.restore(sess, "Saved_model/model.ckpt")
print (sess.run(result))

that is , you can not reuse the restored variable v1 which is from restoring the model file unless you define it befor you restore.
2. although tensorflow doesnot allow reusing the restored variable v1 which is from restoring the model file if you don't define v1 before you restore the model file.
But if you call get_varialbe after you restore the model file, it will create a variable whose name is "v1_1" but not as name='v1' which you specify.
in my opinion, it should be corrected because it is so confusing. how to correct it?
i think get_variable should also reuse the variables which is loaded by restoring some model file.
the last sentence is what i finally want to say.
My english is to bad, you can run the code i offer and will find what i want to convey.
Thanks.

总结

假定一个持久化模型中存在一个V1命名的变量,此时如果使用import_meta_graph方式加载持久化模型。

  • 首先,使用import_meta_graph要加载的持久化模型中的变量命名不能与当前代码默认计算图中的变量命名发生冲突
  • 其次,如果此时希望通过利用tf.get_variable的方式,来建立python变量与计算图变量节点之间的关系,即:
    with tf.variable_scope("",reuse=False):
v1=tf.get_variable(name="v1",shape=[1])
print(v1.name)

是不可能做到的。而且你只能用reuse=False,就好像:加载持久化模型以后,计算图中没有V1变量节点一样。

同时,你使用v1=tf.get_variable(name="v1",shape=[1])方式,会在当前代码的计算图中生成一个新的变量节点V1_1,并非加载的持久化模型中的变量节点V1。此时,就会出现函数功能失效。也就是,你希望调用get_variable函数使得:python的变量v1和计算图中的变量节点v1是绑定的,但是情况并非如此,绑定的是变量节点v1_1。

所以访问计算图中的V1节点,就只能使用tf.get_default_graph().get_tensor_by_name("v1:0")的方式。

很多人可能并不理解这个:0,这是一个operation的输出。也就是说变量节点的输出只有一个,所以用0表示引用计算图中这个变量节点的输出tensor。

事实上,可以自定义tensorflow中的operation,也就是我可以输出多个tensor。那个时候:0,:1就可以用起来了。

总的来说,笔者将此问题提交到gitHub,目前仍然处于欢迎讨论状态。即tensorflow的开发人员需要更多tensorflow使用者的意见,来回答:有没有必要对这个问题进行修复。

6_1 持久化模型与再次加载_探讨(1)_三种持久化模型加载方式以及import_meta_graph方式加载持久化模型会存在的变量管理命名混淆的问题的更多相关文章

  1. android加载大量图片内存溢出的三种方法

    android加载大量图片内存溢出的三种解决办法 方法一:  在从网络或本地加载图片的时候,只加载缩略图. /** * 按照路径加载图片 * @param path 图片资源的存放路径 * @para ...

  2. VC中加载LIB库文件的三种方法

    VC中加载LIB库文件的三种方法 在VC中加载LIB文件的三种方法如下: 方法1:LIB文件直接加入到工程文件列表中   在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中&quo ...

  3. 加载gif动态图的三种方式

    准备:本地图片资源,GifView

  4. Javascript事件模型系列(一)事件及事件的三种模型

    一.开篇 在学习javascript之初,就在网上看过不少介绍javascript事件的文章,毕竟是js基础中的基础,文章零零散散有不少,但遗憾的是没有看到比较全面的系列文章.犹记得去年这个时候,参加 ...

  5. 【转】android加载大量图片内存溢出的三种解决办法

    方法一: 在从网络或本地加载图片的时候,只加载缩略图. /** * 按照路径加载图片 * @param path 图片资源的存放路径 * @param scalSize 缩小的倍数 * @return ...

  6. 页面加载即执行JQuery的三种方法

    [1]$(function( ){ }): $(function(){ $("#name").click(function(){ //adding your code here } ...

  7. linux c++ 加载动态库常用的三种方法

    链接库时的搜索路径顺序:LD_LIBRARY_PATH --> /etc/ld.so.conf --> /lib,/usr/lib 方法1. vi .bash_profile    设置环 ...

  8. 谈IO中的阻塞和非阻塞,同步和异步及三种IO模型

    什么是同步和异步? 烧水,我们都是通过热水壶来烧水的.在很久之前,科技还没有这么发达的时候,如果我们要烧水,需要把水壶放到火炉上,我们通过观察水壶内的水的沸腾程度来判断水有没有烧开.随着科技的发展,现 ...

  9. java面试记录二:spring加载流程、springmvc请求流程、spring事务失效、synchronized和volatile、JMM和JVM模型、二分查找的实现、垃圾收集器、控制台顺序打印ABC的三种线程实现

    注:部分答案引用网络文章 简答题 1.Spring项目启动后的加载流程 (1)使用spring框架的web项目,在tomcat下,是根据web.xml来启动的.web.xml中负责配置启动spring ...

随机推荐

  1. (转)MYSQL线程池总结(一)

    MYSQL线程池总结(一)  原文:http://www.cnblogs.com/cchust/p/4510039.html 线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应 ...

  2. chrome断点调试&&其他技巧

    chrome断点调试 1. 在编写JavaScript代码时,如果 出现了bug,就要不断的去找错误,如果console控制台中提示还好说,可是没有提示恐怕就要费一番周折了.但是有了chrome这个浏 ...

  3. 使用epublib解析epub文件(章节内容、书籍菜单)

    链接地址https://blog.csdn.net/sonnyching/article/details/47407549

  4. chrome 下修改 agent 的方法

    前言 这篇文章和 tiankonguse 的个人网站里的文章保持同步. 很早之前,在 chrome 下修改 agent 的方法是使用 chrome 插件. 后来 chrome 的某一个版本中自带这个功 ...

  5. 自动换行的两种代码(C#)

    最近有个需求,需要将C# winform中的listBox中的内容自动换行, 其实在用listBox前,已经用textBox实现了大部分功能,可惜最后还是有个焦点的问题, 就是textBox中的文字会 ...

  6. Java并发编程笔记之ThreadLocal源码分析

    多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各个操作的顺序是不可预期的,多线程访问同一个共享变量特别容易出现并发问题,特别是多个线程需要对一个共享变量进行写入时候, ...

  7. sublime text3怎么让左侧显示目录树

    在前端开发中(包括Node.js开发),经常会使用sublime text,但之前一直不知道别人是怎么让左侧显示目录树,故特意在此记录一下. View ->Side Bar ->Show ...

  8. 用Shell编写项目发布脚本

    1.首先在github上创建一个测试用的仓库 2.本地编写一个可以运行的测试项目,上传至github 3.链接服务器,编写脚本如下:注意:编写前需要在服务器上安装git和maven 执行build_c ...

  9. 初学者使用MySQL_Workbench 6.0CE创建数据库和表,以及在表中插入数据。

    标签: mysqlworkbench数据库 2013-10-09 20:17 19225人阅读 评论(14) 收藏 举报  分类: mysql(1)  版权声明:本文为博主原创文章,未经博主允许不得转 ...

  10. 微信小程序开发总结(详细)

    转载: 小程序开发总结(详细) 这段时间一直在做小程序,总结下.后续可能会不断更新,努力写仔细点,争取让人看到就能会写. 一,页面结构. 这基本是小程序的标准目录结构.我们从上到下解释下:pages文 ...