TensorFlow2模型的保存与恢复

keras API 保存与加载

保存 Sequential 模型和 Functional 模型

建立用于实验的模型

Sequential 模型和 Functional 模型保存方法相同,用Functional 模型演示:

from tensorflow import keras
from tensorflow.keras import layers


#定义模型
inputs = keras.Input(shape=(784,), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, name='predictions')(x)

model = keras.Model(inputs=inputs, outputs=outputs, name='3_layer_mlp')
model.summary()


#训练模型
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255

model.compile(loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              optimizer=keras.optimizers.RMSprop())
history = model.fit(x_train, y_train,
                    batch_size=64,
                    epochs=1)

Model: "3_layer_mlp"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
digits (InputLayer)          [(None, 784)]             0
_________________________________________________________________
dense_1 (Dense)              (None, 64)                50240
_________________________________________________________________
dense_2 (Dense)              (None, 64)                4160
_________________________________________________________________
predictions (Dense)          (None, 10)                650
=================================================================
Total params: 55,050
Trainable params: 55,050
Non-trainable params: 0
_________________________________________________________________
Train on 60000 samples
60000/60000 [==============================] - 3s 42us/sample - loss: 0.3146

整个模型的保存与恢复

#保存模型
model.save('path_to_my_model.h5')
#恢复模型
new_model = keras.models.load_model('path_to_my_model.h5')

new_model.summary()
Model: "3_layer_mlp"
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
digits (InputLayer)          [(None, 784)]             0
_________________________________________________________________
dense_1 (Dense)              (None, 64)                50240
_________________________________________________________________
dense_2 (Dense)              (None, 64)                4160
_________________________________________________________________
predictions (Dense)          (None, 10)                650
=================================================================
Total params: 55,050
Trainable params: 55,050
Non-trainable params: 0
_________________________________________________________________

当调用model.save方法时:

  • 模型的结构
  • 模型的参数
  • 模型的配置(compile里那些)
  • 模型优化器的相关参数

默认情况下都会被保存,save方法定义如下

save(
    filepath, overwrite=True, include_optimizer=True, save_format=None,
    signatures=None, options=None
)
  • filepath:字符串类型,保存路径
  • overwrite: 是静默覆盖目标位置的任何现有文件,还是向用户提供手动提示。
  • include_optimizer: 是否把优化器内参数也一并保存
  • save_format: 选填’tf’ 和’h5’其中一个, Tensorflow SavedModel 和 HDF5两种类型. 默认是TF
  • signatures: 使用SavedModel保存的签名。只适用于“tf”格式,详情查看 tf.saved_model.save
  • options:可选参数, tf.saved_model.SaveOptions 对象,该对象指定保存到SavedModel的选项。

tf.keras.models.load_model()方法:

tf.keras.models.load_model(
    filepath, custom_objects=None, compile=True
)
  • filepath:加载路径
  • custom_objects: 可选的字典将名称(字符串)映射到在反序列化期间要考虑的自定义类或函数。
  • compile: 是否在加载模型后编译模型

model.save()new_model = keras.models.load_model()同样可将模型导出为SavedModel格式

# Export the model to a SavedModel
model.save('path_to_saved_model', save_format='tf')

# Recreate the exact same model
new_model = keras.models.load_model('path_to_saved_model')

SavedModel是TensorFlow对象的独立序列化格式,由TensorFlow支持和实现。

只保存模型或只保存结构

如果只想保存模型结构,而不想保存模型参数,可以通过model.get_config()方法获取模型的配置信息 , 模型的配置信息是Python dict类型 , 对于模型的恢复可以使用keras.Model.from_config(config)

config = model.get_config()
reinitialized_model = keras.Model.from_config(config)

模型的config信息也可以被保存为json字符串 , 此时应该使用model.to_json()keras.models.model_from_json() , 对模型进行提取和恢复

json_config = model.to_json()
reinitialized_model = keras.models.model_from_json(json_config)

将模型的结构(配置信息)取到内存以后 , 可以通过python方法将模型保存到硬盘:

json_config = model.to_json()
with open('model_config.json', 'w') as json_file:
    json_file.write(json_config)

如果只想保存权重信息可以使用get_weights()/set_weights()方法 , 对模型的权重进行提取和恢复

weights = model.get_weights()  
model.set_weights(weights)  

如果想将其保存在硬盘上,应该用save_weights(fpath)load_weights(fpath),代替 get_weights()set_weights(weights)

model.save_weights方法 :

save_weights(
    filepath, overwrite=True, save_format=None
)
  • filepath: 字符串,文件路径, .h5后缀将会使文件保存为HDF5格式
  • overwrite: 是静默覆盖目标位置的任何现有文件,还是向用户提供手动提示。
  • save_format: 可选 tf 或者 h5 默认不填的话 , 根据文件路径后缀判断 , 否则默认 tf

无论是单独保存参数还是单独保存模型,无论哪种方式,都不会保存训练数据和优化器参数,所以新模型需要重新编译。

子类模型的保存

子类模型的保存和上述类似但是要注意

  • 从未使用过的模型无法被保存
  • 如果使用model.save_weights保存参数,恢复时,需要保证用子类创建一个相同类型的模型,并编译(compile)相同的配置,且在 load_weights之前一定要先训练一些数据(为了自动创建层的大小与类型等操作)

在训练期间保存模型

可以使用训练好的模型而无需从头开始重新训练,或在您打断的地方开始训练,以防止训练过程没有保存。 tf.keras.callbacks.ModelCheckpoint 允许在训练的过程中和结束时回调保存的模型。

tf.keras.callbacks.ModelCheckpoint对象是回调对象,该回调对象可以在每一个周期保存模型

实例化方法:

tf.keras.callbacks.ModelCheckpoint(
    filepath, monitor='val_loss', verbose=0, save_best_only=False,
    save_weights_only=False, mode='auto', save_freq='epoch', **kwargs
)

Arguments:

  • filepath:字符串类型,储存模型的路径
  • monitor: 监视指标val_acc或者val_loss
  • verbose: 日志模型, 0 或者 1.
  • save_best_only: 布尔型,如果为true,根据监视指标,最后一个最好的模型将不会被覆盖,如果filepath 没有包含格式化选项{epoch} ,保存的模型文件将会被新周期里更好的模型覆盖。
  • mode: 可选填{'auto', 'min', 'max'}中的一个,如果save_best_only被设置为true,那么覆盖操作的执行,将根据监视指标和这个参数来决定,比如max val_accmin val_loss ,如果被天填auto则会跟俊监视指标指定选择max 还是min
  • save_weights_only: 如果参数为真,则只保存模型的权值,而非整个模型,这个参数只要影响该回调对象是调用(model.save_weights(filepath)方法还是调用model.save(filepath).
  • save_freq: 填写epoch或者一个数字,如果是epoch时,回调会在每个epoch之后保存模型。当使用integer时,回调将在处理n个样本后保存模型,默认是'epoch'

例如:

checkpoint_path = "training_1/cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)

cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
                                                 save_weights_only=True,
                                                 verbose=1)
history = model.fit(x_train, y_train,
                    batch_size=64,
                    epochs=10, callbacks=[cp_callback])
Train on 60000 samples
Epoch 1/10
58304/60000 [============================>.] - ETA: 0s - loss: 0.3180
Epoch 00001: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 9s 150us/sample - loss: 0.3145
Epoch 2/10
58432/60000 [============================>.] - ETA: 0s - loss: 0.1484
Epoch 00002: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 32us/sample - loss: 0.1476
Epoch 3/10
58624/60000 [============================>.] - ETA: 0s - loss: 0.1077
Epoch 00003: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 31us/sample - loss: 0.1077
Epoch 4/10
58688/60000 [============================>.] - ETA: 0s - loss: 0.0861
Epoch 00004: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 32us/sample - loss: 0.0860
Epoch 5/10
58624/60000 [============================>.] - ETA: 0s - loss: 0.0745
Epoch 00005: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 31us/sample - loss: 0.0742
Epoch 6/10
58624/60000 [============================>.] - ETA: 0s - loss: 0.0630
Epoch 00006: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 31us/sample - loss: 0.0627
Epoch 7/10
58944/60000 [============================>.] - ETA: 0s - loss: 0.0559
Epoch 00007: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 33us/sample - loss: 0.0563
Epoch 8/10
59648/60000 [============================>.] - ETA: 0s - loss: 0.0493
Epoch 00008: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 34us/sample - loss: 0.0493
Epoch 9/10
58816/60000 [============================>.] - ETA: 0s - loss: 0.0431
Epoch 00009: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 34us/sample - loss: 0.0429
Epoch 10/10
58688/60000 [============================>.] - ETA: 0s - loss: 0.0398
Epoch 00010: saving model to training_1/cp.ckpt
60000/60000 [==============================] - 2s 34us/sample - loss: 0.0397

tf.train.Checkpoint 保存与加载

使用tf.train.Checkpoint , 需要首先声明一个 Checkpoint对象:

checkpoint = tf.train.Checkpoint(model=model)

这里 tf.train.Checkpoint() 接受的初始化参数比较特殊,是一个 **kwargs 。具体而言,是一系列的键值对,键名可以随意取,值为需要保存的对象。例如,如果我们希望保存一个继承 tf.keras.Model 的模型实例 model 和一个继承 tf.train.Optimizer 的优化器 optimizer ,我们可以这样写:

checkpoint = tf.train.Checkpoint(myAwesomeModel=model, myAwesomeOptimizer=optimizer)

接下来,当模型训练完成需要保存的时候,使用:

checkpoint.save(save_path_with_prefix)

就可以。 save_path_with_prefix 是保存文件的目录 + 前缀。

当在其他地方需要为模型重新载入之前保存的参数时,需要再次实例化一个 checkpoint,同时保持键名的一致。再调用 checkpoint 的 restore 方法。就像下面这样:

model = MyModel() # 待恢复参数的同一模型
checkpoint = tf.train.Checkpoint(myAwesomeModel=model) # 键名保持为“myAwesomeModel”
checkpoint.restore(save_path_with_prefix_and_index)

即可恢复模型变量。 save_path_with_prefix_and_index 是之前保存的文件的目录 + 前缀 + 编号。例如,调用 checkpoint.restore('./save/model.ckpt-1') 就可以载入前缀为 model.ckpt ,序号为 1 的文件来恢复模型。

当保存了多个文件时,我们往往想载入最近的一个。可以使用 tf.train.latest_checkpoint(save_path) 这个辅助函数返回目录下最近一次 checkpoint 的文件名。例如如果 save 目录下有 model.ckpt-1.indexmodel.ckpt-10.index 的 10 个保存文件, tf.train.latest_checkpoint('./save') 即返回 ./save/model.ckpt-10

tf.train.CheckpointManager 管理检查点

在定义 Checkpoint 后接着定义一个 CheckpointManager:

checkpoint = tf.train.Checkpoint(model=model)
manager = tf.train.CheckpointManager(checkpoint, directory='./save', checkpoint_name='model.ckpt', max_to_keep=k)

此处, directory 参数为文件保存的路径, checkpoint_name 为文件名前缀(不提供则默认为 ckpt ), max_to_keep 为保留的 Checkpoint 数目。

在需要保存模型的时候,我们直接使用 manager.save() 即可。如果我们希望自行指定保存的 Checkpoint 的编号,则可以在保存时加入 checkpoint_number 参数。例如 manager.save(checkpoint_number=100)

本文摘录、翻译自

Keras中文文档
https://keras.io/zh/

TensorFlow官方
https://tensorflow.google.cn/

最全Tensorflow2.0 入门教程持续更新
https://zhuanlan.zhihu.com/p/59507137

简单粗暴TensorFlow2
https://tf.wiki/zh/preface.html

你可能感兴趣的:(深度学习)