Saver的用法
1. Saver的背景介绍
我们经常在训练完一个模型之后希望保存训练的结果,这些结果指的是模型的参数,以便下次迭代的训练或者用作测试。Tensorflow针对这一需求提供了Saver类。
- Saver类提供了向checkpoints文件保存和从checkpoints文件中恢复变量的相关方法。Checkpoints文件是一个二进制文件,它把变量名映射到对应的tensor值 。
- 只要提供一个计数器,当计数器触发时,Saver类可以自动的生成checkpoint文件。这让我们可以在训练过程中保存多个中间结果。例如,我们可以保存每一步训练的结果。
- 为了避免填满整个磁盘,Saver可以自动的管理Checkpoints文件。例如,我们可以指定保存最近的N个Checkpoints文件。
2. Saver的实例
下面以一个例子来讲述如何使用Saver类
1. import tensorflow as tf
2. import numpy as np
4. x = tf.placeholder(tf.float32, shape=[None, 1])
5. y = 4 * x + 4
7. w = tf.Variable(tf.random_normal([1], -1, 1))
8. b = tf.Variable(tf.zeros([1]))
9. y_predict = w * x + b
12. loss = tf.reduce_mean(tf.square(y - y_predict))
13. optimizer = tf.train.GradientDescentOptimizer(0.5)
14. train = optimizer.minimize(loss)
16. isTrain = False
17. train_steps = 100
18. checkpoint_steps = 50
19. checkpoint_dir = ''
21. saver = tf.train.Saver() # defaults to saving all variables - in this case w and b
22. x_data = np.reshape(np.random.rand(10).astype(np.float32), (10, 1))
24. with tf.Session() as sess:
25. sess.run(tf.initialize_all_variables())
26. if isTrain:
27. for i in xrange(train_steps):
28. sess.run(train, feed_dict={x: x_data})
29. if (i + 1) % checkpoint_steps == 0:
30. saver.save(sess, checkpoint_dir + 'model.ckpt', global_step=i+1)
31. else:
32. ckpt = tf.train.get_checkpoint_state(checkpoint_dir)
33. if ckpt and ckpt.model_checkpoint_path:
34. saver.restore(sess, ckpt.model_checkpoint_path)
35. else:
36. pass
37. print(sess.run(w))
38. print(sess.run(b))
isTrain:用来区分训练阶段和测试阶段,True表示训练,False表示测试
train_steps:表示训练的次数,例子中使用100
checkpoint_steps:表示训练多少次保存一下checkpoints,例子中使用50
checkpoint_dir:表示checkpoints文件的保存路径,例子中使用当前路径
2.1 训练阶段
使用Saver.save()方法保存模型:
- sess:表示当前会话,当前会话记录了当前的变量值
- checkpoint_dir + 'model.ckpt':表示存储的文件名
- global_step:表示当前是第几步
训练完成后,当前目录底下会多出5个文件。
打开名为“checkpoint”的文件,可以看到保存记录,和最新的模型存储位置。
2.2测试阶段
测试阶段使用saver.restore()方法恢复变量:
sess:表示当前会话,之前保存的结果将被加载入这个会话
-
ckpt.model_checkpoint_path:表示模型存储的位置,不需要提供模型的名字,它会去查看checkpoint文件,看看最新的是谁,叫做什么。
运行结果如下图所示,加载了之前训练的参数w和b的结果
部分变量保存
默认情况下,saver.save()存储图形的所有变量,一般建议这样做。但是,当我们创建保存对象时,您还可以通过将它们作为列表或字典传入来选择要存储的变量。
v1 = tf.Variable(..., name='v1')
v2 = tf.Variable(..., name='v2')
# pass the variables as a dict:
saver = tf.train.Saver({'v1': v1, 'v2': v2})
# pass them as a list
saver = tf.train.Saver([v1, v2])
# passing a list is equivalent to passing a dict with the variable op names # as keys
saver = tf.train.Saver({v.op.name: v for v in [v1, v2]})
这里使用了三种不同的方式来创建 saver 对象, 但是它们内部的原理是一样的。我们都知道,参数会保存到 checkpoint 文件中,通过键值对的形式在 checkpoint中存放着。如果 Saver 的构造函数中传的是 dict,那么在 save 的时候,checkpoint文件中存放的就是对应的 key-value。如下:
import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")
saver = tf.train.Saver({"variable_1":v1, "variable_2": v2})
# Use the saver object normally after that.
with tf.Session() as sess:
tf.global_variables_initializer().run()
saver.save(sess, 'test-ckpt/model-2')
我们通过官方提供的工具来看一下 checkpoint 中保存了什么
from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
print_tensors_in_checkpoint_file("test-ckpt/model-2", None, True)
# 输出:
#tensor_name: variable_1
#1.0
#tensor_name: variable_2
#2.0
如果构建saver对象的时候,我们传入的是 list, 那么将会用对应 Variable 的 variable.op.name 作为 key。
import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")
saver = tf.train.Saver([v1, v2])
# Use the saver object normally after that.
with tf.Session() as sess:
tf.global_variables_initializer().run()
saver.save(sess, 'test-ckpt/model-2')
我们再使用官方工具打印出 checkpoint 中的数据,得到
tensor_name: v1
1.0
tensor_name: v2
2.0
如果我们现在想将 checkpoint 中v2的值restore到v1 中,v1的值restore到v2中,我们该怎么做?
这时,我们只能采用基于 dict
的 saver
import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")
saver = tf.train.Saver({"variable_1":v1, "variable_2": v2})
# Use the saver object normally after that.
with tf.Session() as sess:
tf.global_variables_initializer().run()
saver.save(sess, 'test-ckpt/model-2')
save
部分的代码如上所示,下面写 restore
的代码,和save
代码有点不同。
```python
import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")
#restore的时候,variable_1对应到v2,variable_2对应到v1,就可以实现目的了。
saver = tf.train.Saver({"variable_1":v2, "variable_2": v1})
# Use the saver object normally after that.
with tf.Session() as sess:
tf.global_variables_initializer().run()
saver.restore(sess, 'test-ckpt/model-2')
print(sess.run(v1), sess.run(v2))
# 输出的结果是 2.0 1.0,如我们所望
我们发现,其实 创建 saver
对象时使用的键值对就是表达了一种对应关系:
- save时, 表示:
variable
的值应该保存到checkpoint
文件中的哪个key
下 - restore时,表示:
checkpoint
文件中key
对应的值,应该restore
到哪个variable
其它
一个快速找到ckpt文件的方式
ckpt = tf.train.get_checkpoint_state(ckpt_dir)
if ckpt and ckpt.model_checkpoint_path:
saver.restore(sess, ckpt.model_checkpoint_path)