tf.train.Saver类的使用
保存模型:
import tensorflow as tf 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() saver=tf.train.Saver() with tf.Session() as sess: sess.run(init_op) saver.save(sess,‘log/model.ckpt‘)
加载模型:
import tensorflow as tf 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 saver=tf.train.Saver() with tf.Session() as sess: ckpt = tf.train.get_checkpoint_state(‘log‘) if ckpt and ckpt.model_checkpoint_path: saver.restore(sess, ckpt.model_checkpoint_path)
在加载模型时,也是先定义tensorflow计算图上的所有运算,但不需要运行变量的初始化,因为变量的值可以通过已经保存的模型加载进来。如果不希望重复定义图上的运算,也可以直接加载已经 持久化的图。
加载计算图:
import tensorflow as tf # 直接加载持久化的图 saver=tf.train.import_meta_graph(‘log/model.ckpt.meta‘) with tf.Session() as sess: saver.restore(sess,‘log/model.ckpt‘) # 通过张量的名称来获取张量 print(sess.run(tf.get_default_graph().get_tensor_by_name(‘add:0‘)))
tf.train.Saver类还支持在保存和加载模型时给变量重命名。
在加载模型时给变量重命名:
import tensorflow as tf # 这里声明的变量名称和已经保存的模型中变量的名称不同。 v1=tf.Variable(tf.constant(1.0,shape=[1]),name=‘new-v1‘) v2=tf.Variable(tf.constant(2.0,shape=[1]),name=‘new-v2‘) # 直接使用tf.train.Saver()加载模型会提示变量找不到的错误# 需要使用一个字典来重命名变量。这个字典指定 # 原来名称为v1的变量现在加载在变量v1中(‘new-v1‘),名称为v2的变量加载到 # 变量v2中(‘new-v2‘) saver=tf.train.Saver({‘v1‘:v1,‘v2‘:v2}) with tf.Session() as sess: saver.restore(sess, ‘log/model.ckpt‘)
重命名的好处是可以方便使用变量的滑动平均值。使用变量的滑动平均值可以让神经网络模型更加健壮。在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.train.ExponentialMovingAverage(0.99) maintain_averages_op=ema.apply(tf.global_variables()) # 在声明滑动平均模型后,tensorflow会自动生成一个影子变量 # 下面语句会输出:‘v:0‘和‘v/ExponentialMovingAverage:0‘ for variables in tf.global_variables(): 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_averages_op) # 保存时,tensorflow会将‘v:0‘和‘v/ExponentialMovingAverage:0‘两个变量都保存下来 saver.save(sess,‘log/model.ckpt‘) print(sess.run([v,ema.average(v)])) # 输出:[10.0, 0.099999905]
基于上面的代码,通过变量重命名直接读取变量的滑动平均值。从程序输出可以看出,读取的变量v的值实际上是上面代码中变量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,‘log/model.ckpt‘) print(sess.run(v)) # 输出:0.099999905
为了方便加载时重命名滑动平均变量,tf.train.ExpoentialMovingAverage类提供了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) # 通过使用variables_to_restore函数来直接生成上面代码中提供的字典 # {‘v/ExponentialMovingAverage‘:v} # 以下代码会输出: # {‘v/ExponentialMovingAverage‘: <tf.Variable ‘v:0‘ shape=() dtype=float32_ref>} print(ema.variables_to_restore()) saver=tf.train.Saver(ema.variables_to_restore()) with tf.Session() as sess: saver.restore(sess,‘log/model.ckpt‘) print(sess.run(v)) # 输出:0.099999905