Blog的Github地址:github.com/liuyan731/b…html
近期作了一些反垃圾的工做,除了使用经常使用的规则匹配过滤等手段,也采用了一些机器学习方法进行分类预测。咱们使用TensorFlow进行模型的训练,训练好的模型须要保存,预测阶段咱们须要将模型进行加载还原使用,这就涉及TensorFlow模型的保存与恢复加载。node
总结一下Tensorflow经常使用的模型保存方式。python
首先,TensorFlow提供了一个很是方便的api,tf.train.Saver()
来保存和还原一个机器学习模型。git
使用tf.train.Saver()
来保存模型文件很是方便,下面是一个简单的例子:github
import tensorflow as tf
import os
def save_model_ckpt(ckpt_file_path):
x = tf.placeholder(tf.int32, name='x')
y = tf.placeholder(tf.int32, name='y')
b = tf.Variable(1, name='b')
xy = tf.multiply(x, y)
op = tf.add(xy, b, name='op_to_store')
sess = tf.Session()
sess.run(tf.global_variables_initializer())
path = os.path.dirname(os.path.abspath(ckpt_file_path))
if os.path.isdir(path) is False:
os.makedirs(path)
tf.train.Saver().save(sess, ckpt_file_path)
# test
feed_dict = {x: 2, y: 3}
print(sess.run(op, feed_dict))
复制代码
程序生成并保存四个文件(在版本0.11以前只会生成三个文件:checkpoint, model.ckpt, model.ckpt.meta)api
以上是tf.train.Saver().save()
的基本用法,save()
方法还有不少可配置的参数:网络
tf.train.Saver().save(sess, ckpt_file_path, global_step=1000)
复制代码
加上global_step参数表明在每1000次迭代后保存模型,会在模型文件后加上"-1000",model.ckpt-1000.index, model.ckpt-1000.meta, model.ckpt.data-1000-00000-of-00001架构
每1000次迭代保存一次模型,可是模型的结构信息文件不会变,就只用1000次迭代时保存一下,不用相应的每1000次保存一次,因此当咱们不须要保存meta文件时,能够加上write_meta_graph=False
参数,以下:机器学习
tf.train.Saver().save(sess, ckpt_file_path, global_step=1000, write_meta_graph=False)
复制代码
若是想每两小时保存一次模型,而且只保存最新的4个模型,能够加上使用max_to_keep
(默认值为5,若是想每训练一个epoch就保存一次,能够将其设置为None或0,可是没啥用不推荐), keep_checkpoint_every_n_hours
参数,以下:函数
tf.train.Saver().save(sess, ckpt_file_path, max_to_keep=4, keep_checkpoint_every_n_hours=2)
复制代码
同时在tf.train.Saver()
类中,若是咱们不指定任何信息,则会保存全部的参数信息,咱们也能够指定部分想要保存的内容,例如只保存x, y参数(可传入参数list或dict):
tf.train.Saver([x, y]).save(sess, ckpt_file_path)
复制代码
ps. 在模型训练过程当中须要在保存后拿到的变量或参数名属性name不能丢,否则模型还原后不能经过get_tensor_by_name()
获取。
针对上面的模型保存例子,还原模型的过程以下:
import tensorflow as tf
def restore_model_ckpt(ckpt_file_path):
sess = tf.Session()
saver = tf.train.import_meta_graph('./ckpt/model.ckpt.meta') # 加载模型结构
saver.restore(sess, tf.train.latest_checkpoint('./ckpt')) # 只须要指定目录就能够恢复全部变量信息
# 直接获取保存的变量
print(sess.run('b:0'))
# 获取placeholder变量
input_x = sess.graph.get_tensor_by_name('x:0')
input_y = sess.graph.get_tensor_by_name('y:0')
# 获取须要进行计算的operator
op = sess.graph.get_tensor_by_name('op_to_store:0')
# 加入新的操做
add_on_op = tf.multiply(op, 2)
ret = sess.run(add_on_op, {input_x: 5, input_y: 5})
print(ret)
复制代码
首先还原模型结构,而后还原变量(参数)信息,最后咱们就能够得到已训练的模型中的各类信息了(保存的变量、placeholder变量、operator等),同时能够对获取的变量添加各类新的操做(见以上代码注释)。
而且,咱们也能够加载部分模型,在此基础上加入其它操做,具体能够参考官方文档和demo。
针对ckpt模型文件的保存与还原,stackoverflow上有一个回答解释比较清晰,能够参考。
同时cv-tricks.com上面的TensorFlow模型保存与恢复的教程也很是好,能够参考。
《tensorflow 1.0 学习:模型的保存与恢复(Saver)》有一些Saver使用技巧。
我本身运行过Tensorflow的inception-v3的demo,发现运行结束后会生成一个.pb的模型文件,这个文件是做为后续预测或迁移学习使用的,就一个文件,很是炫酷,也十分方便。
这个过程的主要思路是graph_def文件中没有包含网络中的Variable值(一般状况存储了权重),可是却包含了constant值,因此若是咱们能把Variable转换为constant(使用graph_util.convert_variables_to_constants()
函数),便可达到使用一个文件同时存储网络架构与权重的目标。
ps:这里.pb是模型文件的后缀名,固然咱们也能够用其它的后缀(使用.pb与google保持一致 ╮(╯▽╰)╭)
一样根据上面的例子,一个简单的demo:
import tensorflow as tf
import os
from tensorflow.python.framework import graph_util
def save_mode_pb(pb_file_path):
x = tf.placeholder(tf.int32, name='x')
y = tf.placeholder(tf.int32, name='y')
b = tf.Variable(1, name='b')
xy = tf.multiply(x, y)
# 这里的输出须要加上name属性
op = tf.add(xy, b, name='op_to_store')
sess = tf.Session()
sess.run(tf.global_variables_initializer())
path = os.path.dirname(os.path.abspath(pb_file_path))
if os.path.isdir(path) is False:
os.makedirs(path)
# convert_variables_to_constants 须要指定output_node_names,list(),能够多个
constant_graph = graph_util.convert_variables_to_constants(sess, sess.graph_def, ['op_to_store'])
with tf.gfile.FastGFile(pb_file_path, mode='wb') as f:
f.write(constant_graph.SerializeToString())
# test
feed_dict = {x: 2, y: 3}
print(sess.run(op, feed_dict))
复制代码
程序生成并保存一个文件
针对上面的模型保存例子,还原模型的过程以下:
import tensorflow as tf
from tensorflow.python.platform import gfile
def restore_mode_pb(pb_file_path):
sess = tf.Session()
with gfile.FastGFile(pb_file_path, 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
sess.graph.as_default()
tf.import_graph_def(graph_def, name='')
print(sess.run('b:0'))
input_x = sess.graph.get_tensor_by_name('x:0')
input_y = sess.graph.get_tensor_by_name('y:0')
op = sess.graph.get_tensor_by_name('op_to_store:0')
ret = sess.run(op, {input_x: 5, input_y: 5})
print(ret)
复制代码
模型的还原过程与checkpoint差很少同样。
CSDN《将TensorFlow的网络导出为单个文件》上介绍了TensorFlow保存单个模型文件的方式,大同小异,能够看看。
模型的保存与加载只是TensorFlow中最基础的部分之一,虽然简单可是也必不可少,在实际运用中还须要注意模型什么时候保存,哪些变量须要保存,如何设计加载实现迁移学习等等问题。
同时TensorFlow的函数和类都在一直变化更新,之后也有可能出现更丰富的模型保存和还原的方法。
选择保存为checkpoint或单个pb文件视业务状况而定,没有特别大的差异。checkpoint保存感受会更加灵活一些,pb文件更适合线上部署吧(我的见解)。
以上完整代码:github
2017/11/25 done
此文章也同步至我的Github博客