解决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实现通过pil模块对图片格式进行转换的方法
Mar 24 Python
python使用datetime模块计算各种时间间隔的方法
Mar 24 Python
python中map、any、all函数用法分析
Apr 21 Python
Python实现的文本简单可逆加密算法示例
May 18 Python
python实现list由于numpy array的转换
Apr 04 Python
pandas带有重复索引操作方法
Jun 08 Python
mac 安装python网络请求包requests方法
Jun 13 Python
python开发之anaconda以及win7下安装gensim的方法
Jul 05 Python
ORM Django 终端打印 SQL 语句实现解析
Aug 09 Python
Python实现的微信红包提醒功能示例
Aug 22 Python
OpenCV Python实现拼图小游戏
Mar 23 Python
python 数据分析实现长宽格式的转换
May 18 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之sphinx
2013/05/15 PHP
基于在生产环境中使用php性能测试工具xhprof的详解
2013/06/03 PHP
PHP根据两点间的经纬度计算距离
2014/10/31 PHP
php文件读取方法实例分析
2015/06/20 PHP
PHP获取数组中指定的一列实例
2017/12/27 PHP
javascript对象的property和prototype是这样一种关系
2007/03/24 Javascript
用JTrackBar实现的模拟苹果风格的滚动条
2007/08/06 Javascript
jquery遍历input取得input的name
2009/04/27 Javascript
ANT 压缩(去掉空格/注释)JS文件可提高js运行速度
2013/04/15 Javascript
JQuery的ready函数与JS的onload的区别详解
2013/11/21 Javascript
JavaScript修改浏览器tab标题小技巧
2015/01/06 Javascript
Javascript调用函数方法的几种方式介绍
2015/03/20 Javascript
JS函数arguments数组获得实际传参数个数的实现方法
2016/05/28 Javascript
利用jQuery.Validate异步验证用户名是否存在(推荐)
2016/12/09 Javascript
详解plotly.js 绘图库入门使用教程
2018/02/23 Javascript
JS将时间秒转换成天小时分钟秒的字符串
2019/07/10 Javascript
Vue-cli 移动端布局和动画使用详解
2020/08/10 Javascript
基于element-ui对话框el-dialog初始化的校验问题解决
2020/09/11 Javascript
[51:29]完美世界DOTA2联赛循环赛 Matador vs Forest BO2第一场 11.05
2020/11/05 DOTA
Python和Perl绘制中国北京跑步地图的方法
2016/03/03 Python
python 信息同时输出到控制台与文件的实例讲解
2018/05/11 Python
python和shell获取文本内容的方法
2018/06/05 Python
Python面向对象之Web静态服务器
2019/09/03 Python
解决Python3.7.0 SSL低版本导致Pip无法使用问题
2020/09/03 Python
分享CSS3中必须要知道的10个顶级命令
2012/04/26 HTML / CSS
canvas实现按住鼠标移动绘制出轨迹的示例代码
2018/02/05 HTML / CSS
CK美国官网:Calvin Klein
2016/08/26 全球购物
意大利团购网站:Groupon意大利
2016/10/11 全球购物
英国行业制服供应商:Alexandra
2019/09/14 全球购物
什么是唯一索引
2015/07/05 面试题
网上卖盒饭创业计划书范文
2014/02/07 职场文书
关于环保的演讲稿
2014/05/10 职场文书
2014年安全生产大检查方案
2014/05/13 职场文书
人力资源求职信
2014/05/25 职场文书
《确定位置》教学反思
2016/02/18 职场文书
Redis sentinel哨兵集群的实现步骤
2022/07/15 Redis