笔者提交到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:
- 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方式加载持久化模型会存在的变量管理命名混淆的问题的更多相关文章
-
android加载大量图片内存溢出的三种方法
android加载大量图片内存溢出的三种解决办法 方法一: 在从网络或本地加载图片的时候,只加载缩略图. /** * 按照路径加载图片 * @param path 图片资源的存放路径 * @para ...
-
VC中加载LIB库文件的三种方法
VC中加载LIB库文件的三种方法 在VC中加载LIB文件的三种方法如下: 方法1:LIB文件直接加入到工程文件列表中 在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中&quo ...
-
加载gif动态图的三种方式
准备:本地图片资源,GifView
-
Javascript事件模型系列(一)事件及事件的三种模型
一.开篇 在学习javascript之初,就在网上看过不少介绍javascript事件的文章,毕竟是js基础中的基础,文章零零散散有不少,但遗憾的是没有看到比较全面的系列文章.犹记得去年这个时候,参加 ...
-
【转】android加载大量图片内存溢出的三种解决办法
方法一: 在从网络或本地加载图片的时候,只加载缩略图. /** * 按照路径加载图片 * @param path 图片资源的存放路径 * @param scalSize 缩小的倍数 * @return ...
-
页面加载即执行JQuery的三种方法
[1]$(function( ){ }): $(function(){ $("#name").click(function(){ //adding your code here } ...
-
linux c++ 加载动态库常用的三种方法
链接库时的搜索路径顺序:LD_LIBRARY_PATH --> /etc/ld.so.conf --> /lib,/usr/lib 方法1. vi .bash_profile 设置环 ...
-
谈IO中的阻塞和非阻塞,同步和异步及三种IO模型
什么是同步和异步? 烧水,我们都是通过热水壶来烧水的.在很久之前,科技还没有这么发达的时候,如果我们要烧水,需要把水壶放到火炉上,我们通过观察水壶内的水的沸腾程度来判断水有没有烧开.随着科技的发展,现 ...
-
java面试记录二:spring加载流程、springmvc请求流程、spring事务失效、synchronized和volatile、JMM和JVM模型、二分查找的实现、垃圾收集器、控制台顺序打印ABC的三种线程实现
注:部分答案引用网络文章 简答题 1.Spring项目启动后的加载流程 (1)使用spring框架的web项目,在tomcat下,是根据web.xml来启动的.web.xml中负责配置启动spring ...
随机推荐
-
ComboBox(下拉列表框)实现省、市、县三级联动,用hibernate连接数据库
package com.hanqi.web; import java.io.IOException; import java.util.List; import javax.servlet.Servl ...
-
hibernate的session对象核心方法注意的问题
1.session.save()方法 1).session.save()方法会使一个对象从临时状态转变为持久化状态. 2).session.save()方法会赋予持久化对象的OID属性一个ID值,以对 ...
-
调研Android平台的开发环境的发展演变
· 安卓是以linux为基础的开放源码操作系统.因为安卓的开源等原因,所以现在市场上会有大量的APP可供使用,且各个方面都功能强大. · 也许是因为开源的原因,安卓过于碎片化.每个APP互相独立. ...
-
Linux Shell 02 流程控制语句
一.if语句格式:支持if/elif/else形式,支持嵌套 1. command执行成功(及退出状态为0)时,执行command2 2. 当判断条件为test命令时,判断结果为true时,执行com ...
-
selenium IDE处理各种窗口问题解决方法
一.处理模态窗口:showModalDialog 由于弹出模态窗口后,就无法定位到当前窗口的元素和模态窗口的元素,需要添加js解决 模态窗口动作类似下面语句: <input id="c ...
-
VC++ win32 多线程 一边画圆一边画矩形
// WinThreadTest.cpp : Defines the entry point for the application. // #include "stdafx.h" ...
-
WinForm界面布局
一直很羡慕和佩服园子中伍华聪的界面设计和布局.好多年都没有真正写过C/S项目了,今天翻出来6年前刚开始学习WinForm的时候写的一个简单的HR管理系统,思绪一下子很复杂,记得是6年前的夏天,天气很热 ...
-
自定义spring mvc的json视图
场景 前端(安卓,Ios,web前端)和后端进行了数据的格式规范的讨论,确定了json的数据格式: { "code":"200", "data&quo ...
-
CF 291E. Tree-String Problem [dfs kmp trie图优化]
CF291E 题意:一棵树,每条边上有一些字符,求目标串出现了多少次 直接求目标串的fail然后一边dfs一边跑kmp 然后就被特殊数据卡到\(O(n^2)\)了... 因为这样kmp复杂度分析的基础 ...
-
爬一下国家统计局行政区划代码C#
目前NBS上有2015-2018四个年度的代码信息,写一个控制台程序爬一下县级行政区下的代码. 使用HttpWebRequest+HttpWebResponse获取html,使用HtmlAgility ...