训练一个模型时,你需要使用变量来保存和更新权值。变量是在内存缓冲区内的tensor,它们必须被显式初始化并且可以在模型训练之后被存储到硬盘中。接着,你就可以重载被保存的值来练习和分析模型。
本文参考两个tensorflow类,可以进入下面的链接获取完整的API描述:
创建
- The
tf.Variable
class. - The
tf.train.Saver
class.
当你创建一个变量,你要传递一个tensor到Variable()构造器作为它的初始值。Tensorflow提供了很多用来生成tensor的操作,tensor通常从常量或随机值来初始化。
注意,这些操作都要求你指定tensor的形状,指定的形状会自动的变成变量的大小。变量通常是固定大小的,但tensorflow提供了重塑变量大小的高级机制。
# Create two variables.
weights = tf.Variable(tf.random_normal([784,200], stddev=0.35),name="weights")
biases = tf.Variable(tf.zeros([200]), name="biases")
调用tf.Variable()会在计算图上添加几个操作:
- 一个储存变量值的变量操作
- 一个给变量设置初始值的初始化操作,这通常是一个tf.assign操作
- 对初始值的操作,例如例子中对偏置值的0初始操作就被添加到计算图中
tf.Variable()返回的结果值是Python类tf.Variable的实例。
指定设备
当一个变量被创建的时候,它可以通过with tf.device(...):块被分配到指定的设备上:
# Pin a variable to CPU.
with tf.device("/cpu:0"):
v = tf.Variable(...)
# Pin a variable to GPU.
with tf.device("/gpu:0"):
v = tf.Variable(...)
# Pin a variable to a particular parameter server task.
with tf.device("/job:ps/task:7"):
v = tf.Variable(...)
注意:能改变变量的操作,例如tf.Variable.assign以及参数更新操作tf.train.Optimizer必须与变量运行在同一个设备上。不兼容的变量存放指令会在创建时就被忽略掉。指定设备在运行于重复设置时显得特别重要。用于简化设备配置的函数细节详见
tf.train.replica_device_setter
。初始化
参数初始化必须显式的先于模型其他操作运行。最简单的方式是添加一个初始化所有参数的操作,然后在训练模型之前运行这个操作。
你也可以通过重载checkpoint文件以获得变量值。
使用tf.global_variables_initializer()可以添加一个操作来运行初始化器。在完整构造模型后运行这个初始化器,接着就可以在会话(Session)中开始训练你的模型。
# Create two variables.
weights = tf.Variable(tf.random_normal([784,200], stddev=0.35), name="weights")
biases = tf.Variable(tf.zeros([200]), name="biases")
...
# Add an op to initialize the variables.
init_op = tf.global_variables_initializer()
# Later, when launching the model
with tf.Session()as sess: # Run the init operation.
sess.run(init_op)
...
# Use the model
...
基于其他变量初始化
有时候你需要利用其他参数的初始值来初始化一个变量。当初始化被tf.global_variables_initializer()操作添加且并行地执行所有变量的初始化时,你必须格外小心。
从另一个变量值初始化一个新变量需要使用其他变量的initialized_value()方法。你可以直接使用(其他变量的)初始值作为新变量,或者你可以使用它作为其他tensor来计算一个新变量的值。
# Create a variable with a random value.
weights = tf.Variable(tf.random_normal([784,200], stddev=0.35), name="weights")
# Create another variable with the same value as 'weights'.
w2 = tf.Variable(weights.initialized_value(), name="w2")
# Create another variable with twice the value of 'weights'
w_twice = tf.Variable(weights.initialized_value()*2.0, name="w_twice")
常规初始化
tf.global_variables_initializer()这一便捷的函数添加一个操作来初始化模型中的所有变量。你也可以显式地传递一列变量来使用tf.variables_initializer进行初始。浏览关于变量的文档来获取更多的选项,包括检查你的变量是否已经被初始化
保存和重载一个模型最简单的方法是使用一个
tf.train.Saver
对象。构造器会对所有或部分指定的变量添加save和restore操作到计算图上。saver对象提供方法来运行这些操作,可以指定checkpoint文件的路径进行写出或读取。
注意,要重载一个模型的checkpoint而不附带计算图的话,必须首先从元计算图文件(通常扩展名是.meta)加载一个计算图。这样的操作可以通过tf.train.import_meta_graph实现,这个方法会返回一个能用来重载的Saver对象。
Checkpoint文件
保存变量
选择所需保存和重载的变量
变量会被存储于一个二进制文件中,这个文件会包含从变量名到tensor值的映射。当你创建一个Saver对象的时候,你可以在checkpoint文件中为变量选择名称。默认每个变量名会使用tf.Variable.name属性值。为了搞明白什么变量在checkpoint中,你可以使用inspect_checkpoint库的print_tensors_in_checkpoint_file函数。
通过tf.train.Saver()创建一个Saver来管理模型中的所有变量。
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add an op to initialize the variables.
init_op = tf.global_variables_initializer()
# Add ops to save and restore all the variables.
saver = tf.train.Saver()
# Later, launch the model, initialize the variables, do some work, save the
# variables to disk.
with tf.Session()as sess:
sess.run(init_op)
# Do some work with the model.
...
# Save the variables to disk.
save_path = saver.save(sess,"/tmp/model.ckpt")
print("Model saved in file: %s"% save_path)
重载变量
Saver对象同样可以用来重载变量。注意当你从一个文件中重载变量时,你不一定要事先初始化它们。
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add ops to save and restore all the variables.
saver = tf.train.Saver()
# Later, launch the model, use the saver to restore variables from disk, and
# do some work with the model.
with tf.Session()as sess:
# Restore variables from disk.
saver.restore(sess,"/tmp/model.ckpt")
print("Model restored.")
# Do some work with the model
...
如果你不传递任何参数到tf.train.Saver()中的话,saver会处理计算图中的所有变量。每个变量会被保存在它被创建时所指定的名称下。
有时在checkpoint文件中为变量显式指定名称是很有用的。例如你可能已经训练好一个拥有名叫“weights”的变量的模型,可以重载这个变量值到一个名叫“params”的新变量中。
另外,只保存模型中变量的一个子集有时也是很有用的。例如你可能已经训练好一个5层的神经网络,而你现在想要训练一个6层的新模型,可以从先前训练的模型中重载5层参数到新模型的前5层。
你可以通过传递一个以名称为key且以变量为value的Python字典到tf.train.Saver()构造器中进行简易地存储。
注意:
- 你可以根据你的需要创建任意多的saver来保存和重载模型变量的不同子集。相同的变量可以被指定到多个saver对象中,它的值只会在saver的restore()方法运行的时候被改变。
- 如果你在会话开始只重载模型变量的一个子集,你必须对其他变量进行一个初始化操作。更多信息请见
tf.variables_initializer
。
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add ops to save and restore only 'v2' using the name "my_v2"
saver = tf.train.Saver({"my_v2": v2})
# Use the saver object normally after that
....