解决tensorflow模型参数保存和加载的问题


Posted in Python onJuly 26, 2018

终于找到bug原因!记一下;还是不熟悉平台的原因造成的!

Q:为什么会出现两个模型对象在同一个文件中一起运行,当直接读取他们分开运行时训练出来的模型会出错,而且总是有一个正确,一个读取错误? 而 直接在同一个文件又训练又重新加载模型预测不出错,而且更诡异的是此时用分文件里的对象加载模型不会出错?

model.py,里面含有 ModelV 和 ModelP,另外还有 modelP.py 和 modelV.py 分别只含有 ModelP 和 ModeV 这两个对象,先使用 modelP.py 和 modelV.py 分别训练好模型,然后再在 model.py 里加载进来:

# -*- coding: utf8 -*-

import tensorflow as tf

class ModelV():

 def __init__(self):

  self.v1 = tf.Variable(66, name="v1")
  self.v2 = tf.Variable(77, name="v2")
  self.save_path = "model_v/model.ckpt"
  self.init = tf.global_variables_initializer()
  self.saver = tf.train.Saver()
  self.sess = tf.Session()

 def train(self):
  self.sess.run(self.init)
  print 'v2', self.v2.eval(self.sess)

  self.saver.save(self.sess, self.save_path)
  print "ModelV saved."

 def predict(self):

  all_vars = tf.trainable_variables()
  for v in all_vars:
   print(v.name)
  self.saver.restore(self.sess, self.save_path)
  print "ModelV restored."
  print 'v2', self.v2.eval(self.sess)
  print '------------------------------------------------------------------'

class ModelP():

 def __init__(self):

  self.p1 = tf.Variable(88, name="p1")
  self.p2 = tf.Variable(99, name="p2")
  self.save_path = "model_p/model.ckpt"
  self.init = tf.global_variables_initializer()
  self.saver = tf.train.Saver()
  self.sess = tf.Session()

 def train(self):
  self.sess.run(self.init)
  print 'p2', self.p2.eval(self.sess)

  self.saver.save(self.sess, self.save_path)
  print "ModelP saved."

 def predict(self):

  all_vars = tf.trainable_variables()
  for v in all_vars:
   print v.name
  self.saver.restore(self.sess, self.save_path)
  print "ModelP restored."
  print 'p2', self.p2.eval(self.sess)
  print '---------------------------------------------------------------------'


if __name__ == '__main__':
 v = ModelV()
 p = ModelP()
 v.predict()
 #v.train()
 p.predict() 
 #p.train()

这里 tf.global_variables_initializer() 很关键! 尽管你是分别在对象 ModelP 和 ModelV 内部分配和定义的 tf.Variable(),即 v1 v2 和 p1 p2,但是 对 tf 这个模块而言, 这些都是全局变量,可以通过以下代码查看所有的变量,你就会发现同一个文件中同时运行 ModelP 和 ModelV 在初始化之后都打印出了一样的变量,这个是问题的关键所在:

all_vars = tf.trainable_variables()
for v in all_vars:
 print(v.name)

错误。你可以交换 modelP 和 modelV 初始化的顺序,看看错误信息的变化

v1:0
v2:0
p1:0
p2:0
ModelV restored.
v2 77
v1:0
v2:0
p1:0
p2:0
W tensorflow/core/framework/op_kernel.cc:975] Not found: Key v2 not found in checkpoint
W tensorflow/core/framework/op_kernel.cc:975] Not found: Key v1 not found in checkpoint

实际上,分开运行时,模型保存的参数是正确的,因为在一个模型里的Variable就只有 v1 v2 或者 p1 p2; 但是在一个文件同时运行的时候,模型参数实际上保存的是 v1 v2 p1 p2四个,因为在默认情况下,创建的Saver,会直接保存所有的参数。而 Saver.restore() 又是默认(无Variable参数列表时)按照已经定义好的全局模型变量来加载对应的参数值, 在进行 ModelV.predict时,按照顺序(从debug可以看出,应该是按照参数顺序一次检测)在模型文件中查找相应的 key,此时能够找到对应的v1 v2,加载成功,但是在 ModelP.predict时,在model_p的模型文件中找不到 v1 和 v2,只有 p1 和 p2, 此时就会报错;不过这里的 第一次加载 还有 p1 p2 找不到没有报错,解释不通, 未完待续

Saver.save() 和 Saver.restore() 是一对, 分别只保存和加载模型的参数, 但是模型的结构怎么知道呢? 必须是你定义好了,而且要和保存的模型匹配才能加载;

如果想要在不定义模型的情况下直接加载出模型结构和模型参数值,使用

# 加载 结构,即 模型参数 变量等
new_saver = tf.train.import_meta_graph("model_v/model.ckpt.meta")
print "ModelV construct"
all_vars = tf.trainable_variables()
for v in all_vars:
 print v.name
 #print v.name,v.eval(self.sess) # v 都还未初始化,不能求值
# 加载模型 参数变量 的 值
new_saver.restore(self.sess, tf.train.latest_checkpoint('model_v/'))
print "ModelV restored."
all_vars = tf.trainable_variables()
for v in all_vars:
 print v.name,v.eval(self.sess)

加载 结构,即 模型参数 变量等完成后,就会有变量了,但是不能访问他的值,因为还未赋值,然后再restore一次即可得到值了

那么上述错误的解决方法就是这个改进版本的model.py;其实 tf.train.Saver 是可以带参数的,他可以保存你想要保存的模型参数,如果不带参数,很可能就会保存 tf.trainable_variables() 所有的variable,而 tf.trainable_variables()又是从 tf 全局得到的,因此只要在模型保存和加载时,构造对应的带参数的tf.train.Saver即可,这样就会保存和加载正确的模型了

# -*- coding: utf8 -*-

import tensorflow as tf

class ModelV():

 def __init__(self):

  self.v1 = tf.Variable(66, name="v1")
  self.v2 = tf.Variable(77, name="v2")
  self.save_path = "model_v/model.ckpt"
  self.init = tf.global_variables_initializer()

  self.sess = tf.Session()

 def train(self):
  saver = tf.train.Saver([self.v1, self.v2])
  self.sess.run(self.init)
  print 'v2', self.v2.eval(self.sess)

  saver.save(self.sess, self.save_path)
  print "ModelV saved."

 def predict(self):
  saver = tf.train.Saver([self.v1, self.v2])
  all_vars = tf.trainable_variables()
  for v in all_vars:
   print v.name

  v_vars = [v for v in all_vars if v.name == 'v1:0' or v.name == 'v2:0']
  print "ModelV restored."
  saver.restore(self.sess, self.save_path)
  for v in v_vars:
   print v.name,v.eval(self.sess) 
  print 'v2', self.v2.eval(self.sess)
  print '------------------------------------------------------------------'

class ModelP():

 def __init__(self):

  self.p1 = tf.Variable(88, name="p1")
  self.p2 = tf.Variable(99, name="p2")
  self.save_path = "model_p/model.ckpt"
  self.init = tf.global_variables_initializer()
  self.sess = tf.Session()

 def train(self):
  saver = tf.train.Saver([self.p1, self.p2])
  self.sess.run(self.init)
  print 'p2', self.p2.eval(self.sess)

  saver.save(self.sess, self.save_path)
  print "ModelP saved."

 def predict(self):
  saver = tf.train.Saver([self.p1, self.p2])
  all_vars = tf.trainable_variables()
  p_vars = [v for v in all_vars if v.name == 'p1:0' or v.name == 'p2:0']
  for v in all_vars:
   print v.name
   #print v.name,v.eval(self.sess)
  saver.restore(self.sess, self.save_path)
  print "ModelP restored."
  for p in p_vars:
   print p.name,p.eval(self.sess)
  print 'p2', self.p2.eval(self.sess)
  print '----------------------------------------------------------'


if __name__ == '__main__':
 v = ModelV()
 p = ModelP()
 v.predict()
 #v.train()
 p.predict() 
 #p.train()

小结: 构造的Saver 最好带Variable参数,这样保证 保存和加载能够正确执行

以上这篇解决tensorflow模型参数保存和加载的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python开发之tkinter实现图形随鼠标移动的方法
Nov 11 Python
Python实现Youku视频批量下载功能
Mar 14 Python
Python使用正则表达式获取网页中所需要的信息
Jan 29 Python
Python中多个数组行合并及列合并的方法总结
Apr 12 Python
Python使用paramiko操作linux的方法讲解
Feb 25 Python
python框架Django实战商城项目之工程搭建过程图文详解
Mar 09 Python
python访问hdfs的操作
Jun 06 Python
python Socket网络编程实现C/S模式和P2P
Jun 22 Python
Python延迟绑定问题原理及解决方案
Aug 04 Python
Python为何不支持switch语句原理详解
Oct 21 Python
python如何正确使用yield
May 21 Python
教你怎么用Python selenium操作浏览器对象的基础API
Jun 23 Python
解决tensorflow1.x版本加载saver.restore目录报错的问题
Jul 26 #Python
Flask web开发处理POST请求实现(登录案例)
Jul 26 #Python
基于tensorflow加载部分层的方法
Jul 26 #Python
利用python画出折线图
Jul 26 #Python
浅谈flask源码之请求过程
Jul 26 #Python
python画折线图的程序
Jul 26 #Python
TensorFlow利用saver保存和提取参数的实例
Jul 26 #Python
You might like
PHP 进程锁定问题分析研究
2009/11/24 PHP
php二维数组用键名分组相加实例函数
2013/11/06 PHP
PHP实现将textarea的值根据回车换行拆分至数组
2015/06/10 PHP
js表数据排序 sort table data
2009/02/18 Javascript
javascript 嵌套的函数(作用域链)
2010/03/15 Javascript
基于jquery的多彩百分比 动态进度条 投票效果显示效果实现代码
2011/08/28 Javascript
IE下JS读取xml文件示例代码
2013/08/05 Javascript
ie 7/8不支持trim的属性的解决方案
2014/05/23 Javascript
JS生成随机字符串的多种方法
2014/06/10 Javascript
javascript框架设计读书笔记之字符串的扩展和修复
2014/12/02 Javascript
JavaScript严格模式详解
2015/11/18 Javascript
原生JavaScript实现Ajax的方法
2016/04/07 Javascript
BootStrap智能表单实战系列(九)表单图片上传的支持
2016/06/13 Javascript
NodeJs中express框架的send()方法简介
2017/06/20 NodeJs
对vue中v-if的常见使用方法详解
2018/09/28 Javascript
微信小程序封装的HTTP请求示例【附升级版】
2019/05/11 Javascript
js实现简单点赞操作
2020/03/17 Javascript
JavaScript中的函数式编程详解
2020/08/22 Javascript
python web.py开发httpserver解决跨域问题实例解析
2018/02/12 Python
Python使用selenium实现网页用户名 密码 验证码自动登录功能
2018/05/16 Python
Python 实现中值滤波、均值滤波的方法
2019/01/09 Python
Python实现TCP探测目标服务路由轨迹的原理与方法详解
2019/09/04 Python
pytorch多GPU并行运算的实现
2019/09/27 Python
Python sql注入 过滤字符串的非法字符实例
2020/04/03 Python
详解PyQt5中textBrowser显示print语句输出的简单方法
2020/08/07 Python
Pycharm github配置实现过程图解
2020/10/13 Python
纪伊国屋泰国网上书店:Kinokuniya泰国
2017/12/24 全球购物
建筑设计学生的自我评价
2014/01/16 职场文书
材料成型及控制工程专业求职信
2014/06/19 职场文书
物业消防安全责任书
2014/07/23 职场文书
2014年工程工作总结
2014/11/25 职场文书
工作推荐信模板
2015/03/25 职场文书
Java生成读取条形码和二维码的简单示例
2021/07/09 Java/Android
数据分析数据库ClickHouse在大数据领域应用实践
2022/04/03 MySQL
最新动漫情报:2022年7月新番定档超过30部, OVERLORD骨王第四季也在其中噢
2022/05/04 日漫
python 判断字符串当中是否包含字符(str.contain)
2022/06/01 Python