TensorFlow(5)——模型保存与恢复(Saver类)
在使⽤TensorFlow搭建深度学习框架时,需要将训练好的模型的参数保存下来,以便下⼀次继续⽤于训练或测试,这个过程称为TensorFlow模型持久化。
TensorFlow提供了⼀个⾮常简单的API来保存和恢复⼀个神经⽹络模型,这个AP就是tf.train.Saver类。
1 TensorFlow模型⽂件
TensorFlow在保存模型时,将计算图的结构和图上的参数数值分开保存,最终得到以下4个⽂件:
checkpoint
model.ckpt-5.data-00000-of-00001
model.ckpt-5.index
a
⽂件名model.ckpt并不是后缀为.ckpt的⽂件,⽽是⽤户⾃定义的模型⽂件名,你可以将它⾃定义为任何你想要的名字,但⼀般⽽⾔,⼤家都把TensorFlow模型⽂件名定义为model.ckpt,以表⽰该⽂件是checkpoint⽂件。
model.ckpt后的-5也是模型⽂件名的⼀部分,表⽰神经⽹络在第⼏轮训练后保存的模型,与参数global_step有关(后续例⼦将会⽤到)。
1.1 checkpoint⽂件
getsavefilenamecheckpoint⽂件保存了⼀个⽬录下所有的模型⽂件列表。该⽂件是tf.train.Saver类⾃动⽣成且⾃动维护的。在checkpoint⽂件中维护了⼀个有tf.train.Saver类持久化的所有TensorFlow模型⽂件的⽂件名。当某个保存的TensorFlow模型⽂件被删除时,这个模型⽂件所对应的⽂件名也会从checkpoint⽂件中移除。
checkpoint⽂件有两个属性:
model_checkpoint_path:保存了最新的TensorFlow模型⽂件的⽂件名。
all_model_checkpoint_paths:列出了当前还没有被删除的所有TensorFlow模型⽂件的⽂件名。
1.2 .data⽂件
该⽂件是数据⽂件,保存了TensorFlow程序中所有变量的数值(计算图上的参数数值),可以看成是神经⽹络的参数值等。
1.3 .meta⽂件
该⽂件保存了TensorFlow的计算图,可以看成是神经⽹络的⽹络结构。
1.4 .index⽂件
该⽂件是⼀个不可变得字符串表,每⼀个键都是张量的名称,它的值是⼀个序列化的BundleEntryProto。 每个BundleEntryProto描述张量的元数据:“数据”⽂件中的哪个⽂件包含张量的内容,该⽂件的偏移量,校验和,⼀些辅助数据等等。
2 模型保存与恢复
saver = tf.train.Saver(var_list=None,
max_to_keep=5,
keep_checkpoint_every_n_hours=10000.0)
var_list : 要保存的变量名列表;默认为None,即保存所有的变量。
max_to_keep : 所保存的模型⽂件的最⼤数量;默认为5,即最多保存5个模型⽂件,当第6次调⽤saver.save()时,第1个模型⽂件(最先被保存的模型⽂件)将会被TensorFlow⾃动删除,依次类推,以保证最多只保存了最新的max_to_keep个模型⽂件。好处是:避免保存过多的模型⽂件,节省磁盘空间。
keep_checkpoint_every_n_hours:通过设置该参数,每n个⼩时可以在max_to_step的基础上多保存依次模型。
注意:上述只给出实例化Saver类时最常⽤的3个参数,⽽Saver类还有很多参数,⼤家可根据需要,⾃⾏设置。
2.1 模型保存
⼀般⽽⾔,如果不指定任何参数,tf.train.Saver类会保存所有的参数。保存模型时⽤saver.save()⽅法
saver.save(sess,
save_path,
global_step=None,
latest_filename=None,
meta_graph_suffix="meta",
write_meta_graph=True,
write_state=True,
strip_default_attrs=False)
sess:会话
save_path:模型保存路径,即模型⽂件名
global_step:表⽰训练轮数,如果global_step有值,则模型⽂件名变成“save_path-global_step”。
write_meta_graph:是否保存计算图。在神经⽹路训练时,神经⽹络的结构⼀般是不变的,所以计算图也是不变的,因此我们不需要每次保存变量数值时都保存计算图(第⼀次保存就⾏),此时可以将 write_meta_graph设置为False。
2.1.1 实例1——基本形式
import tensorflow as tf
import os
model_dir ="./my_model"
if not ists(model_dir):
os.makedirs(model_dir)
checkpoint_path = os.path.join(model_dir,"model.ckpt")
a = tf.get_variable("a",[2,3], tf.float32, s_initializer)
b = tf.get_variable("b",[2,3], tf.float32, s_initializer)
init = tf.global_variables_initializer()
saver = tf.train.Saver()
with tf.Session()as sess:
sess.run(init)
saver.save(sess, checkpoint_path)
得到如下模型⽂件:
2.1.2 实例2——设置max_to_keep和global_step
import tensorflow as tf
import os
model_dir ="./my_model"
if not ists(model_dir):
os.makedirs(model_dir)
checkpoint_path = os.path.join(model_dir,"model.ckpt")
a = tf.Variable(tf.random_normal([1,2]), name="a")
b = tf.Variable(tf.random_normal([1,2]), name="b")
init = tf.global_variables_initializer()
saver = tf.train.Saver(max_to_keep=2)
with tf.Session()as sess:
sess.run(init)
print("a =", sess.run(a))
print("b =", sess.run(b))
for step in range(10):
saver.save(sess, checkpoint_path, global_step=step+1)
将max_to_keep设置为2,并在模型⽂件名后添加global_step,得到如下模型⽂件和屏幕输出结果:
a = [[ 1.5390072 -0.69095516]]
b = [[-0.10171167 0.3147837 ]]
2.1.3 实例3——只保存⼀次计算图
import tensorflow as tf
import os
model_dir ="./my_model"
if not ists(model_dir):
os.makedirs(model_dir)
checkpoint_path = os.path.join(model_dir,"model.ckpt")
a = tf.Variable(tf.random_normal([1,2]), name="a")
b = tf.Variable(tf.random_normal([1,2]), name="b")
init = tf.global_variables_initializer()
saver = tf.train.Saver(max_to_keep=2)
with tf.Session()as sess:
sess.run(init)
for step in range(10):
saver.save(sess, checkpoint_path, global_step=step+1, write_meta_graph=False)
metagraph_filename = os.path.join(model_dir,'a')
# 只保存⼀次图
if not ists(metagraph_filename):
得到以下模型⽂件:
2.2 模型恢复
使⽤store()⽅法来加载模型
2.2.0 如何到模型⽂件
使⽤store(sess, checkpoint_path)⽅法来加载模型,需要输⼊模型⽂件名 checkpoint_path,如果你知道准确的模型⽂件名,那直接输就⾏。但是,在实际使⽤时,会添加global_step,随着训练轮数的增加,训练后的最新模型⽂件名是会变化的,所以很难⼿动输⼊。
解决以上问题的常⽤⽅法有两种:
⽅法1
checkpoint_dir ="./my_model/"
ckpt = _checkpoint_state(checkpoint_dir)
if ckpt del_checkpoint_path:
checkpoint_path = del_checkpoint_path
分析:使⽤_checkpoint_state(checkpoint_dir)
该函数输⼊模型⽂件的⽬录checkpoint_dir,然后读取并返回checkpoint⽂件的内容(1.1的那张图)
import tensorflow as tf
checkpoint_dir ="./my_model/"
ckpt = _checkpoint_state(checkpoint_dir )
print(ckpt)
del_checkpoint_path)
输出结果:
model_checkpoint_path: "./my_model/model.ckpt-10"
all_model_checkpoint_paths: "./my_model/model.ckpt-9"
all_model_checkpoint_paths: "./my_model/model.ckpt-10"
./my_model/model.ckpt-10
显然del_checkpoint_path就是我们要的最新的模型⽂件名。
⽅法2
checkpoint_dir ="./my_model/"
checkpoint_path = tf.train.latest_checkpoint(checkpoint_dir)
查看tf.train.latest_checkpoint()后会发现,其实⽅法1是⽅法2的简易版本。
2.2.1 实例1——⼿动重新搭建计算图
import tensorflow as tf
checkpoint_path ="./my_model/model.ckpt-10"
a = tf.Variable(tf.random_normal([1,2]), name="a")
b = tf.Variable(tf.random_normal([1,2]), name="b")
saver = tf.train.Saver()
with tf.Session()as sess:
print("a =", sess.run(a))
print("b =", sess.run(b))
输出结果:
a = [[ 1.5390072 -0.69095516]]
b = [[-0.10171167 0.3147837 ]]
该加载模型的⽅法是最基本的⽅法,这段代码与2.1.1中保存模型代码的
共同点:都需要在会话前构建TensorFlow计算图;
区别是:在保存模型前需要初始化变量,在加载模型时不需要初始化变量,变量的初始值由store()加载得到。注意:store()只加载变量值,不加载计算图,因此store()只能在计算图内使⽤,否则会报错。2.2.2 实例2——直接加载已存在的计算图
深度神经⽹络的计算图是庞⼤且复杂的,当我们使⽤别⼈的预训练⽹络权值时,使⽤2.2.1的⽅法⼿动搭建计算图显然是不可⾏的,这是我们可以直接加载别⼈的计算图。
完整代码:
import tensorflow as tf
checkpoint_dir ="./my_model/"
with tf.Session()as sess:
ckpt = _checkpoint_state(checkpoint_dir)
if ckpt del_checkpoint_path:
checkpoint_path = del_checkpoint_path
saver = tf.train.import_meta_graph(checkpoint_path +".meta")
graph = tf.get_default_graph()
a = _tensor_by_name('a:0')
b = _tensor_by_name('b:0')
print("a =", sess.run(a))
print("b =", sess.run(b))
输出结果:
a =[[1.5390072-0.69095516]]
b =[[-0.101711670.3147837]]
上述代码⾸先判断是否存在模型⽂件,如果存在,则
1. 使⽤tf.train.import_meta_graph()来加载计算图;
2. 使⽤tf.get_default_graph()来获取所加载的计算图;
3. ⽤get_tensor_by_name()来获取计算图上的变量(或⽤get_operation_by_name()来获取计算图上op);
4. 最后通过store()来加载模型⽂件中的变量数值,实现对变量进⾏初始化。
注意:前3个步骤属于构建计算图部分,可以放在会话之外进⾏,即
import tensorflow as tf
checkpoint_dir ="./my_model/"
ckpt = _checkpoint_state(checkpoint_dir)
if ckpt del_checkpoint_path:
checkpoint_path = del_checkpoint_path
saver = tf.train.import_meta_graph(checkpoint_path +".meta")
graph = tf.get_default_graph()
a = _tensor_by_name('a:0')
b = _tensor_by_name('b:0')
with tf.Session()as sess:
print("a =", sess.run(a))
print("b =", sess.run(b))
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论