笔者提交到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拆库

    原文:http://www.cnblogs.com/cchust/p/3859967.html 互联网网站应用大多采用mysql作为DB存储,限于mysql单机性能的瓶颈,为了支撑更大容量和更大的访问 ...

  2. 漫谈NIO(3)之Netty实现

    1.前言 上一章结合Java的NIO例子,讲解了多路IO复用的一个基本使用方法,通过实际编码加深对其理解.本章开始进入Netty的环节,前面两章都是为了Netty进行铺垫说明.此节将对比Java的NI ...

  3. Linux下安装jdk8步骤详述(转载)

    Linux下安装jdk8步骤详述 原文地址:http://www.cnblogs.com/shihaiming/p/5809553.html 作为Java开发人员,在Linux下安装一些开发工具是必备 ...

  4. 手风琴图片和钢琴导航栏JQ滑动特效

    手风琴JQ滑动特效 1.效果预览: 2.相关代码: <!DOCTYPE html> <html lang="en"> <head> <me ...

  5. 【树】Sum Root to Leaf Numbers

    题目: Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a nu ...

  6. Dock的生态开源技术(Etcd&Machine&Compose&Swarm&Mesos&Kubernetes)

    Etcd CoreOS公司开源的高可用分布式键值数据库Etcd,该项目已经被广泛应用到分布式系统的一致性实现和服务发现中,基于Go语言实现. Etcd就是专门为集群环境设计,可以很好地实现数据一致性, ...

  7. JVM内存限制和调整

    今天用java -jar执行一个jar文件提示内存不够,需要设置虚拟机的堆大小.以下是参考资料: 堆(Heap)和非堆(Non-heap)内存  按照官方的说法:“Java 虚拟机具有一个堆,堆是运行 ...

  8. nodeJs的npm报错问题

    1. Failed at the phantomjs-prebuilt@2.1.14 install script 'node install.js'. 解决办法: npm install phant ...

  9. aapt命令获取apk详细信息(包名、版本号、版本名称、兼容api级别、启动Activity等)

    1.安装SDK,使用SDK自带的aapt进行查看.aapt所在位置:D:\SDK\build-tools下,任一一个均可,如D:\SDK\build-tools\19.1.0 2.cmd命令下进入ap ...

  10. T24银行核心业务系统

    T24银行核心业务系统 http://www.pianshen.com/search http://www.pianshen.com/article/8248107255/