一、模型的保存与载入方式(一)
1、模型的保存
使用下面这两行指令对训练的模型进行保存
- saver = tf.train.Saver() # 定义Saver用于保存模型
- saver.save(sess,'models/my_model.ckpt') # 保存模型
以简单的手写字符识别(MNIST)为例,训练一个一层的神经网络:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 载入数据集
mnist = input_data.read_data_sets("MNIST_data",one_hot=True)
# 每个批次64张照片
batch_size = 64
# 计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_size
# 定义两个placeholder
# 给模型数据输入的入口起名为x-input
x = tf.placeholder(tf.float32,[None,784], name='x-input')
# 给模型标签输入的入口起名为y-input
y = tf.placeholder(tf.float32,[None,10], name='y-input')
# 创建一个简单的神经网络,输入层784个神经元,输出层10个神经元
W = tf.Variable(tf.truncated_normal([784,10],stddev=0.1))
b = tf.Variable(tf.zeros([10])+0.1)
# 给模型输出起名为output
prediction = tf.nn.softmax(tf.matmul(x,W)+b, name='output')
# 交叉熵代价函数
loss = tf.losses.softmax_cross_entropy(y,prediction)
# 使用Adam优化器,给优化器operation起名为train
train_step = tf.train.AdamOptimizer(0.001).minimize(loss, name='train')
# 初始化变量
init = tf.global_variables_initializer()
# 求准确率
# tf.argmax(y,1)中的1表示取y中第1个维度中最大值所在的位置
# tf.equal表示比较两个值是否相等,相等返回True,不相等返回False
# 最后correct_prediction是一个布尔型的列表
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))
# tf.cast表示数据格式转换,把布尔型转为float类型,True变成1.0,False变成0.0
# tf.reduce_mean求平均值
# 最后accuracy为准确率
# 给准确率tensor起名为accuracy
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32), name='accuracy')
# 定义Saver用于保存模型
saver = tf.train.Saver()
with tf.Session() as sess:
# 变量初始化
sess.run(init)
# 运行11个周期
for epoch in range(11):
for batch in range(n_batch):
# 获取一个批次的数据和标签
batch_xs,batch_ys = mnist.train.next_batch(batch_size)
# 喂到模型中做训练
sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys})
# 每个周期计算一次测试集准确率
acc = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
# 打印信息
print("Iter " + str(epoch) + ",Testing Accuracy " + str(acc))
# 保存模型
saver.save(sess,'models/my_model.ckpt')
保存得到的右边这四个模型文件:
- my_model.ckpt.meta:模型的结构,也就是前面定义的神经网络结构;
- my_model.ckpt:模型的参数:权值与偏置。
2、模型的载入(一)
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 载入数据集
mnist = input_data.read_data_sets("MNIST_data",one_hot=True)
# 定义批次大小
batch_size = 64
# 计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_size
with tf.Session() as sess:
# 载入模型结构
saver = tf.train.import_meta_graph('models/my_model.ckpt.meta')
# 载入模型参数
saver.restore(sess,'models/my_model.ckpt')
# 根据tensor的名字获取到对应的tensor
# 之前保存模型的时候模型输出保存为output,":0"是保存模型参数时自动加上的,所以这里也要写上
output = sess.graph.get_tensor_by_name('output:0')
# 根据tensor的名字获取到对应的tensor
# 之前保存模型的时候准确率计算保存为accuracy,":0"是保存模型参数时自动加上的,所以这里也要写上
accuracy = sess.graph.get_tensor_by_name('accuracy:0')
# 之前保存模型的时候模型训练保存为train,注意这里的train是operation不是tensor
train_step = sess.graph.get_operation_by_name('train')
# 把测试集喂到网络中计算准确率
# x-input是模型数据的输入,":0"是保存模型参数时自动加上的,所以这里也要写上
# y-input是模型标签的输入,":0"是保存模型参数时自动加上的,所以这里也要写上
print(sess.run(accuracy,feed_dict={'x-input:0':mnist.test.images,'y-input:0':mnist.test.labels}))
# 在原来模型的基础上再训练11个周期
for epoch in range(11):
for batch in range(n_batch):
# 获取一个批次的数据和标签
batch_xs,batch_ys = mnist.train.next_batch(batch_size)
# 训练模型
sess.run(train_step,feed_dict={'x-input:0':batch_xs,'y-input:0':batch_ys})
# 计算测试集准确率
acc = sess.run(accuracy,feed_dict={'x-input:0':mnist.test.images,'y-input:0':mnist.test.labels})
# 打印信息
print("Iter " + str(epoch) + ",Testing Accuracy " + str(acc))
3、模型的载入(二)——针对只有模型参数文件‘.ckpt’,需要自己重新搭建模型结构
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 载入数据集
mnist = input_data.read_data_sets("MNIST_data",one_hot=True)
# 定义批次大小
batch_size = 64
# 计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_size
# 定义两个placeholder
x = tf.placeholder(tf.float32,[None,784])
y = tf.placeholder(tf.float32,[None,10])
# 创建一个简单的神经网络,输入层784个神经元,输出层10个神经元
# 这里的模型参数需要跟之前训练好的模型参数一样
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
prediction = tf.nn.softmax(tf.matmul(x,W)+b)
# 计算准确率
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
# 定义saver用于载入模型
# max_to_keep=5,在指定路径下最多保留5个模型,超过5个模型就会删除老的模型
saver = tf.train.Saver(max_to_keep=5)
# 交叉熵代价函数
loss = tf.losses.softmax_cross_entropy(y,prediction)
# 使用Adam优化器
train_step = tf.train.AdamOptimizer(0.001).minimize(loss)
# 定义会话
with tf.Session() as sess:
# 变量初始化
sess.run(tf.global_variables_initializer())
# 计算测试集准确率
print(sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels}))
# 载入训练好的参数
saver.restore(sess,'models/my_model.ckpt')
# 再次计算测试集准确率
print(sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels}))
# 在原来模型的基础上再训练11个周期
for epoch in range(11):
for batch in range(n_batch):
# 获取一个批次的数据和标签
batch_xs,batch_ys = mnist.train.next_batch(batch_size)
# 训练模型
sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys})
# 计算测试集准确率
acc = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
# 打印信息
print("Iter " + str(epoch) + ",Testing Accuracy " + str(acc))
# 保存模型,global_step可以用来表示模型的训练次数或者训练周期数
saver.save(sess,'models/my_model.ckpt',global_step=epoch)
二、模型的保存与载入方式(二)
1、模型的保存
使用下面指令实现模型的保存:
# 保存模型参数和结构,把变量变成常量
output_graph_def = tf.graph_util.convert_variables_to_constants(sess, sess.graph_def, output_node_names=['output','accuracy']) #output_node_names设置可以输出的tensor
# 保存模型到目录下的models文件夹中,保存为.pb文件
with tf.gfile.FastGFile('pb_models/my_model.pb',mode='wb') as f:
f.write(output_graph_def.SerializeToString())
还是以手写数字识别为例:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 载入数据集
mnist = input_data.read_data_sets("MNIST_data",one_hot=True)
# 每个批次64张照片
batch_size = 64
# 计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_size
# 定义两个placeholder
# 给模型数据输入的入口起名为x-input
x = tf.placeholder(tf.float32,[None,784], name='x-input')
# 给模型标签输入的入口起名为y-input
y = tf.placeholder(tf.float32,[None,10], name='y-input')
# 创建一个简单的神经网络,输入层784个神经元,输出层10个神经元
W = tf.Variable(tf.truncated_normal([784,10],stddev=0.1))
b = tf.Variable(tf.zeros([10])+0.1)
# 给模型输出起名为output
prediction = tf.nn.softmax(tf.matmul(x,W)+b, name='output')
# 交叉熵代价函数
loss = tf.losses.softmax_cross_entropy(y,prediction)
# 使用Adam优化器,给优化器operation起名为train
train_step = tf.train.AdamOptimizer(0.001).minimize(loss, name='train')
# 初始化变量
init = tf.global_variables_initializer()
# 求准确率
# tf.argmax(y,1)中的1表示取y中第1个维度中最大值所在的位置
# tf.equal表示比较两个值是否相等,相等返回True,不相等返回False
# 最后correct_prediction是一个布尔型的列表
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))
# tf.cast表示数据格式转换,把布尔型转为float类型,True变成1.0,False变成0.0
# tf.reduce_mean求平均值
# 最后accuracy为准确率
# 给准确率tensor起名为accuracy
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32), name='accuracy')
with tf.Session() as sess:
# 变量初始化
sess.run(init)
# 运行11个周期
for epoch in range(11):
for batch in range(n_batch):
# 获取一个批次的数据和标签
batch_xs,batch_ys = mnist.train.next_batch(batch_size)
# 喂到模型中做训练
sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys})
# 每个周期计算一次测试集准确率
acc = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
# 打印信息
print("Iter " + str(epoch) + ",Testing Accuracy " + str(acc))
# 保存模型参数和结构,把变量变成常量
# output_node_names设置可以输出的tensor
output_graph_def = tf.graph_util.convert_variables_to_constants(sess, sess.graph_def, output_node_names=['output','accuracy'])
# 保存模型到目录下的models文件夹中
with tf.gfile.FastGFile('pb_models/my_model.pb',mode='wb') as f:
f.write(output_graph_def.SerializeToString())
2、模型的载入
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 载入数据集
mnist = input_data.read_data_sets("MNIST_data",one_hot=True)
# 载入模型
with tf.gfile.FastGFile('pb_models/my_model.pb', 'rb') as f:
# 创建一个图
graph_def = tf.GraphDef()
# 把模型文件载入到图中
graph_def.ParseFromString(f.read())
# 载入图到当前环境中
tf.import_graph_def(graph_def, name='')
with tf.Session() as sess:
# 根据tensor的名字获取到对应的tensor
# 之前保存模型的时候模型输出保存为output,":0"是保存模型参数时自动加上的,所以这里也要写上
output = sess.graph.get_tensor_by_name('output:0')
# 根据tensor的名字获取到对应的tensor
# 之前保存模型的时候准确率计算保存为accuracy,":0"是保存模型参数时自动加上的,所以这里也要写上
accuracy = sess.graph.get_tensor_by_name('accuracy:0')
# 预测准确率
print(sess.run(accuracy,feed_dict={'x-input:0':mnist.test.images,'y-input:0':mnist.test.labels}))
三、总结
- 模型保存为.pb文件比保存为.ckpt文件,占用的内存更小;
- 相比较而言,.pb的模型载入方式比.ckpt载入方式更简便;
- 由于.pb方式模型保存是将模型参数转变为常量形式保存,所以.pb方式适合用来保存已经训练好的模型,直接用来模型结果来做预测;而.ckpt方式则适合用来保存未训练好的模型,方便之后对模型的进一步训练。