前一天讨论了tensorboard今天讨论在TensorFlow1.x中的模型保存
和加载使用
。但
是在实际开发中我们不会
简单的将模型上传服务器,开发api接口调用的,因为
将模型放在服务器上,使用标准API接口文档编写也可以实现推理功能。但是,这种方式可能会涉及到一些额外的工作,例如:设置部署环境
、处理并发请求
、处理模型版本
和更新
等问题。这样的工作需要进行更多的编程和配置,而且可能不够灵活和可扩展。
这里涉及的技术例如: TF服务
等,今天就先不讨论,明天详细讨论这里。
SavedModel
格式:SavedModel 是 TensorFlow 推荐的模型格式,可以将模型保存为一个目录,其中包含了模型结构、变量和运行时信息。SavedModel 可以跨平台、跨语言地加载模型,并支持部署到 TensorFlow Serving 等服务中。
Checkpoint
文件:Checkpoint 文件是 TensorFlow 训练的中间结果,保存了所有变量和权重的值。可以使用 tf.train.Saver()
将变量保存到 Checkpoint 文件中,也可以使用 tf.train.latest_checkpoint()
加载最新的 Checkpoint 文件。
Keras
模型文件:Keras 是 TensorFlow 的高级 API,可以使用 keras.models.save_model()
方法将 Keras 模型保存为 HDF5
或 SavedModel
格式的文件。
Protocol Buffer
文件:TensorFlow 使用 Protocol Buffer 格式来序列化和反序列化数据,包括模型结构、变量和运行时信息。可以使用 tf.io.write_graph() 和 tf.io.read_graph() 方法将模型保存为或加载为 GraphDef Protocol Buffer 文件。
我们只讨论 第二种
和第三种
,以适用我们在不同场景中的使用。
Save()
类Saver
类的保存方法属于第二种方法
,即Checkpoint
文件。 Saver是TensorFlow提供的一个用于保存
和恢复模型变量
的类。它可以将训练过程中的模型参数保存到硬盘上,以便在需要的时候重新加载模型参数。
通过tf.train.Saver
类创建 saver
对象
元计算图
:计算图的协议缓冲区定义,扩展名为.meta
检查点
:各种变量的值,包含两个文件,一个是扩展名为.index的,另一个是 文件扩展名为data-0000-of-00001
检查点
(Checkpoint)是保存
训练过程中模型的参数值
的文件。当我们训练一个模型时,可以定期保存模型参数
的当前值为一个检查点文件
,以便在训练过程中出现故障或需要更改超参数时,能够从上一个检查点恢复训练,而不用重新开始训练。
通过使用检查点文件
,我们可以将训练过程分成若干个阶段
,每个阶段保存一个检查点文件,以便在训练过程中出现意外情况(如程序意外退出、计算机断电等)时能够快速恢复模型。检查点还可以用于
在训练过程中选择最佳的模型
。我们可以通过比较不同的检查点文件,选择验证集分类准确率最高或损失函数最小的模型作为最终结果。
var_list
: 可选参数,表示需要保存或恢复的变量列表,默认为所有可训练变量。
reshape
: 可选参数,如果为True,则载入模型时会尝试自动将变量reshape成原来的形状,默认为False。
sharded
: 可选参数,如果为True,则在保存数据时将其分割成多个文件进行存储(仅当save_relative_paths=True时有效),默认为False。
max_to_keep
: 可选参数,表示最多保存的检查点数量,默认为5。
keep_checkpoint_every_n_hours
: 可选参数,表示每隔多少小时保存一个检查点,默认为10000个步骤保存一次。
name
: 可选参数,表示Saver对象的名称。
重要函数参数
:session
, save_path
, global_step=None, latest_filename=None, meta_graph_suffix=‘meta’, write_meta_graph=True, write_state=True, strip_default_attrs=False, save_debug_info=False):session
:表示当前Session,save_path
:表示保存路径,session
:表示当前Session,save_path
:表示保存路径,var_list
:表示需要恢复的变量列表,默认为所有可训练变量,TensorFlow 2.x
中的Saver
类被tf.train.Checkpoint
取代了
tf.train.Saver()
该函数可以创建一个Saver对象
,用于保存
和恢复
TensorFlow模型。你可以使用saver.save()
方法将模型保存到磁盘上,也可以使用saver.restore()
方法从磁盘上恢复模型。
saver.save(sess, save_path)
该方法可以将当前会话(Session)的所有变量保存到磁盘上,其中参数sess是一个已经打开的会话,save_path是要保存的模型文件的路径。
tf.train.import_meta_graph(meta_graph_def)
该函数可以从.meta文件中导入图结构(Graph),其中meta_graph_def是一个包含图定义信息的.meta
文件。
saver.restore(sess, save_path)
该方法可以从指定的模型文件中恢复所有变量,其中参数sess是一个已经打开的会话,save_path是之前保存的模型文件的路径。
tf.get_default_graph()
该函数可以获取默认的计算图(Graph),在加载模型时需要借助该函数来获取图中的所有节点和变量。
graph.get_tensor_by_name(name)
该方法可以根据节点名称获取计算图中的张量(Tensor)。
graph.get_operation_by_name(name)
该方法可以根据节点名称获取计算图中的操作(Operation)。
仅保存模型结构
(Architecture):使用 model.to_json()
方法将模型结构保存为 JSON 文件
格式,使用 model_from_json()
方法加载模型结构。
保存模型结构和权重
(Weights):使用 model.save_weights()
方法将模型权重保存为 HDF5 文件
格式,使用 load_weights()
方法加载模型权重。此外,还可以
使用 model.save()
方法保存整个模型,包括模型结构和权重
,也是以 HDF5 文件格式进行保存
。
保存完整的模型对象
,包括模型结构
、权重
和编译信息
等:使用 tf.keras.models.save_model() 方法将整个模型保存为 SavedModel 格式或者 HDF5 文件格式,使用 tf.keras.models.load_model() 方法加载模型。如果需要保存模型的编译信息,例如优化器、损失函数、评估指标等,则需要设置 save_format=‘tf’ 参数,以保存为 SavedModel 格式。
这三种方式的主要区别在于保存的内容不同。第一种方式
只保存了模型的结构,无法直接使用;第二种方式
保存了模型的权重,可以方便地用于继续训练或者对新数据进行预测;第三种方式
保存了完整的模型对象,可以方便地复现模型,并且包含了模型的结构、权重和编译信息。
第三种方式还支持保存为 SavedModel 格式
,这是 TensorFlow 官方推荐的模型保存格式,可以方便地部署
到 TensorFlow Serving
或者其他平台上。而 HDF5 文件格式则更加通用
,可以在不同框架之间
进行转换和共享。
save = tf.train.Saver()
with tf.Session() as sess:
...
save.save(sess,'./')
'''
参数一:会话对象
参数二:保存的路径以及名字
'''
with tf.Session() as sess:
...
save.restore(sess,'./')
import tensorflow as tf
from tensorflow.python.client import device_lib
import os
print(device_lib.list_local_devices())
tf.reset_default_graph()
with tf.device("/device:cpu:0"):
# create w and b init 0.0
w = tf.Variable(0.0, name='weight')
b = tf.Variable(0.0, name='bias')
# create input and out
x = tf.placeholder(dtype=tf.float32, shape=[None])
out = tf.placeholder(dtype=tf.float32, shape=[None])
# create loss and opt
y = w * x + b
loss = tf.reduce_mean(tf.square(y - out))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train_op = optimizer.minimize(loss)
config = tf.ConfigProto()
config.log_device_placement=True
output_scalar = tf.reduce_mean(y) # 将 y 变量转换为标量
loss_scalar = tf.reduce_mean(loss)
# 记录标量数据(输出结果和损失值)
tf.summary.scalar('output', output_scalar)
tf.summary.scalar('loss', loss_scalar)
# 记录张量数据(权重和偏置项)
tf.summary.histogram('weight', w)
tf.summary.histogram('bias', b)
# 记录网络结构
with tf.name_scope('hidden'):
h = tf.nn.sigmoid(y)
tf.summary.histogram('activation', h)
#实例化模型保存对象
save = tf.train.Saver()
# train model
with tf.Session(config=config) as sess:
# 合并所有的摘要操作
merged = tf.summary.merge_all()
# 创建摘要写入器
writer = tf.summary.FileWriter('./logss', sess.graph)
#注意!!!在保存模型的时候 需要进行变量初始化
tf.global_variables_initializer().run(session=sess)
for i in range(100000):
summary,_, loss_val, w_val, b_val = sess.run(
[merged,train_op, loss, w, b],
feed_dict={x: [1, 23, 4, 5, 7, 5, 7], out: [3, 5, 7, 9, 11, 13, 15]}
) #注意 输入的数据 形状要一致,避免输出与预测值得形状不一致问题
if i % 100 == 0:
print('Step {}: loss = {}, w = {}, b = {}'.format(i, loss_val, w_val, b_val))
writer.add_summary(summary, i)
#保存模型
save_model_file = save.save(sess,'./model.ckpt')
其实
:加载模型进行预测就是使用训练的模型变量
对会话进行初始化
。一般我们训练的时候会对变量进行全局初始化,在加载模型的时候改为 训练好的模型变量。
import tensorflow as tf
from tensorflow.python.client import device_lib
import os
print(device_lib.list_local_devices())
tf.reset_default_graph()
with tf.device("/device:cpu:0"):
# create w and b init 0.0
w = tf.Variable(0.0, name='weight')
b = tf.Variable(0.0, name='bias')
# create input and out
x = tf.placeholder(dtype=tf.float32, shape=[None])
out = tf.placeholder(dtype=tf.float32, shape=[None])
# create loss and opt
y = w * x + b
# loss = tf.reduce_mean(tf.square(y - out))
# optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
# train_op = optimizer.minimize(loss)
config = tf.ConfigProto()
config.log_device_placement=True
#实例化保存对象
save = tf.train.Saver()
# train model
with tf.Session(config=config) as sess:
save.restore(sess,'./')
#加载模型的时候不需要进行变量初始化
# tf.global_variables_initializer().run(session=sess)
outs = sess.run(
[y],
feed_dict={x:[1,2,3]}
) #注意 输入的数据 形状要一致,避免输出与预测值得形状不一致问题
print('outs;',outs)