TensorFlow模型持久化

1、持久化代码实现

    TensorFlow提供了一个非常简单的API来保存和还原一个神经网络模型。这个API是tf.train.Saver类。以下代码给出保存Tensorflow计算图的方法

import tensorflow as tf

#声明两个变量并计算他们的和
v1 = tf.Variable(tf.constant(1.0,shape=[1],name="other-v1"))
v2 = tf.Variable(tf.constant(2.0,shape=[1],name="other-v2"))
result = v1 + v2

init_op = tf.global_variables_initializer()

#声明tf.train.Saver类用于保存模型
saver = tf.train.Saver()

with tf.Session() as sess:
    sess.run(init_op)
    saver.save(sess, "/path/to/model/model.ckpt")

上面这些代码会生成的第一个文件为model.ckpt.meta,他保存了TensorFlow计算图的结构。第二个文件为model.ckpt,他保存了TensorFlow程序中每一个变量的取值。最后一个文件为checkpoint文件,这个文件保存了一个目录下所有的模型文件列表。

import tensorflow as tf

#声明两个变量并计算他们的和
v1 = tf.Variable(tf.constant(1.0,shape=[1],name="other-v1"))
v2 = tf.Variable(tf.constant(2.0,shape=[1],name="other-v2"))
result = v1 + v2

#声明tf.train.Saver类用于保存模型
saver = tf.train.Saver()

with tf.Session() as sess:
    #加载已经保存的模型,并通过已经保存的模型中变量的值来计算加法
    saver.restore(sess, "/path/to/model/model.ckpt")
    sess.run(result)

上面两段代码唯一的不同是,在加载模型的代码中没有运行变量的初始化过程,而是将变量的值通过已经保存的模型加载进来。如果不希望重复定义图上的计算可以直接加载持久化的图,代码如下

import tensorflow as tf

#直接加载持久化的图
saver = tf.train.import_meta_graph("/path/to/model/model.ckpt/model.ckpt.meta")

with tf.Session() as sess:
    #加载已经保存的模型,并通过已经保存的模型中变量的值来计算加法
    saver.restore(sess, "/path/to/model/model.ckpt")
    #通过张量的名称来获取张量
    print(sess.run(tf.get_default_graph().get_tensor_by_name("add:0")))
    #输出[3.]

下面的代码说明重命名是如何被使用的

import tensorflow as tf

#声明两个变量并计算他们的和
v1 = tf.Variable(tf.constant(1.0,shape=[1],name="other-v1"))
v2 = tf.Variable(tf.constant(2.0,shape=[1],name="other-v2"))

#如果直接使用tf.train.Saver()来加载模型会报变量找不到错误。下面显示了报错信息
#tensorflow.python.framework.errors.NotFoundError:Tensor name "other-v2"
#not found in checkpoint files /path/to/model/model.ckpt

#使用一个字典来重命名变量可以就可以加载原来的模型了。
#这个字典指定了原来名称为v1的变量现在加载到变凉v1中(名称为other-v1),
#名称为v2的变量加载到变量v2(名称为other-v2)
saver = tf.train.Saver({"v1":v1. "v2":v2})

这个程序中,对变量v1和v2的名称进行修改。如果直接通过tf.train.Saver默认的构造函数来加载保存的模型,那么程序会报变量找不到的错误。因为保存时候变量的名称和加载时候的变凉名称不一致。为了解决这个问题,Tensorflow可以通过字典将保存是的变量名和需要加载的变量联系起来。这样做的主要目的之一是为了方便使用变凉的滑动平均值。

import tensorflow as tf
v = tf.Variable(0, dtype=tf.float32, name="v")
#在没有申明滑动平均模型时只有一个变凉v,所以以下语句智慧输出“v:0”
for variables in tf.global_variables():
    print(variables.name)

ema = tf.tf.train.ExponentialMovingAverage(0.99)
maintain_averages_op = ema.apply(tf.global_variables())
#在声明华东平均模型之后,TensorFlow会自动生成一个影子变量
#v/ExponentialMoving Average.于是以下语句会输出
#"v:0" 和 "v/ExponentialMovingAverage:0"
for variables in tf.global_varibales():
    print(variables.name)

saver = tf.train.Saver()
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    
    sess.run(tf.assign(v, 10))
    sess.run(maintain_average_op)
    #保存时,TensorFlow会将v:0和v/ExponentialMovingAverage:0两个变量都保存下来。
    saver.save(sess, "path/to/model/model/ckpt")
    print(sess.run([v, ema.average(v)]))

如何读取变量的滑动平均值

v = tf.Variable(0, dtype=tf.float32, name="v")

#通过变量重命名将原来变量v的滑动平均值直接赋值给v
saver = tf.train.Saver({"v/ExponentialMovingAverage":v})

with tf.Session() as sess:
    saver.restore(sess, "/path/to/model/model/ckpt")
    print(sess.run(v))    #输出0.999999905,这个值就是原来模型中变量v的滑动平均值

为了方便加载时重命名滑动平均值,tf.train.ExponentialMovingAverage类提供了variables_to_restore函数来生成tf.train.Saver类所需要的变量重命名字典。以下代码为实例

import tensorflow as tf
v = tf.Variable(0, dtype=tf.float32, name='v')
ema = tf.train.ExponentialMovingAverage(0.99)

#通过使用variable_to_restore函数可以直接生成上面代码中提供的字典
#{"v/ExponentialMovingAverage":<tensorflow.Variable 'v:0' shape=() dtype=float32_ref>}
#其中后面的Variable类就代表了变量v
print(ema.variables_to_restore())

saver = tf.train.Saver(ema.variables_to_restore())
with tf.Session() as sess:
    saver.restore(sess, "/path/to/model/model.ckpt")
    print(sess.run(v))

convert_variables_to_constants函数,将计算图中的变量及其取值通过常量及其取值通过常量的方式保存,这样整个TensorFlow计算图可以统一存放在一个文件中,如下代码

import tensorflow as tf
from tensorflow.python.framework import graph_util

v1 = tf.Variable(tf.constant(1.0, shape=[1], name="v1"))
v2 = tf.Variable(tf.constant(2.0, shape=[1], name="v2"))
result=v1+v2

init_op = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init_op)
    #导出当前计算图的DraphDef部分,只需要这一部分就可以完成从输入层到输出层的计算过程
    graph_def = tf.get_default_graph().as_graph_def()
    
    #将图中的变量及其取值转化为常量,同时将图中不必要的节点去掉。
    #下列代码中["add"]给出了需要保存的节点名称,add节点是上面定义的两个变量相加的操作,这里给出的是计算节点的名称,所以没有后面的:0

    output_graph_def=graph_util.convert_variables_to_constants(sess, graph_def, ['add'])
    #将导出的模型存入文件
    with tf.gfile.GFile("/path/to/model/combined_model.pb","wb") as f:
        f.write(output_graph_def.SerializeToString())

通过以下程序直接计算定义的加法运算结果。

import tensorflow as tf
from tensorflow.python.platform import gfile

with tf.Session() as sess:
    model_filename = "/path/to/model/combined_model.pb"
    #读取保存的模型文件,并将文件解析成对应的GraphDef Protocol Buffer
    with gfile.FastGFile(model_filename, 'rb') as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())


#将graph_def中保存的图加载到当前的图中。return_elements=["add:0"]给出了返回的张量的名称,在保存的时候给出的是计算节点的名称,所以为“add”.在加载的时候给出的是张量的名称,所以是“add:0”
    result = tf.import_graph_def(graph_def, return_elements=["add:0"])
    #输出[3.0]
    print(sess.run(result)) 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值