跳至主要內容

〔TensorFlow〕保存与恢复模型

大林鸱大约 5 分钟深度学习计算机视觉自然语言处理

前面章节中我们使用《初学者的 TensorFlow 2.0 教程》已经训练了一个图像分类模型,但并没有保存模型。

这篇教程我会保持持续更新,随着学习的深入,将模型保存和恢复相关功能都整理出来。

说明

模型信息包括:

  • 结构
  • 权重
  • 配置
  • 优化器状态

保存模型的结构

使用 model.to_json()搭配 tf.keras.models.model_from_json()对模型的结构进行保存与恢复

  • 保存
import json

# 生成json文件
model_json = model.to_json()
# 写入json文件
with open(r'model_json.json', 'w') as f:
    json.dump(model_json, f)
    print('模型的结构json文件保存完成!')

结果

{
  "module": "keras",
  "class_name": "Sequential",
  "config": {
    "name": "sequential",
    "trainable": true,
    "dtype": "float32",
    "layers": [
      {
        "module": "keras.layers",
        "class_name": "InputLayer",
        "config": { "batch_shape": [null, 28, 28], "dtype": "float32", "sparse": false, "name": "input_layer" },
        "registered_name": null
      },
      {
        "module": "keras.layers",
        "class_name": "Flatten",
        "config": { "name": "flatten", "trainable": true, "dtype": "float32", "data_format": "channels_last" },
        "registered_name": null,
        "build_config": { "input_shape": [null, 28, 28] }
      },
      {
        "module": "keras.layers",
        "class_name": "Dense",
        "config": {
          "name": "dense",
          "trainable": true,
          "dtype": "float32",
          "units": 128,
          "activation": "relu",
          "use_bias": true,
          "kernel_initializer": {
            "module": "keras.initializers",
            "class_name": "GlorotUniform",
            "config": { "seed": null },
            "registered_name": null
          },
          "bias_initializer": { "module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null },
          "kernel_regularizer": null,
          "bias_regularizer": null,
          "kernel_constraint": null,
          "bias_constraint": null
        },
        "registered_name": null,
        "build_config": { "input_shape": [null, 784] }
      },
      {
        "module": "keras.layers",
        "class_name": "Dropout",
        "config": { "name": "dropout", "trainable": true, "dtype": "float32", "rate": 0.2, "seed": null, "noise_shape": null },
        "registered_name": null
      },
      {
        "module": "keras.layers",
        "class_name": "Dense",
        "config": {
          "name": "dense_1",
          "trainable": true,
          "dtype": "float32",
          "units": 10,
          "activation": "linear",
          "use_bias": true,
          "kernel_initializer": {
            "module": "keras.initializers",
            "class_name": "GlorotUniform",
            "config": { "seed": null },
            "registered_name": null
          },
          "bias_initializer": { "module": "keras.initializers", "class_name": "Zeros", "config": {}, "registered_name": null },
          "kernel_regularizer": null,
          "bias_regularizer": null,
          "kernel_constraint": null,
          "bias_constraint": null
        },
        "registered_name": null,
        "build_config": { "input_shape": [null, 128] }
      }
    ],
    "build_input_shape": [null, 28, 28]
  },
  "registered_name": null,
  "build_config": { "input_shape": [null, 28, 28] },
  "compile_config": {
    "optimizer": "adam",
    "loss": {
      "module": "keras.losses",
      "class_name": "SparseCategoricalCrossentropy",
      "config": { "name": "sparse_categorical_crossentropy", "reduction": "sum_over_batch_size", "from_logits": true, "ignore_class": null },
      "registered_name": null
    },
    "loss_weights": null,
    "metrics": ["accuracy"],
    "weighted_metrics": null,
    "run_eagerly": false,
    "steps_per_execution": 1,
    "jit_compile": false
  }
}
  • 恢复
# 从磁盘读取json文件
with open('model_json.json') as json_file:
    json_config = json_file.read()
new_model = keras.models.model_from_json(json_config)

保存模型的权重

#将权重写入磁盘,文件后缀要求是.weights.h5
model.save_weights('model_weights.weights.h5')

#从磁盘读取权重文件
model.load_weights('model_weights.weights.h5')

保存模型

保存网络结构、权重、配置、优化器状态。

# 保存模型,可以是.h5或.keras格式
model.save('model.h5')

# 加载模型,同时加载了模型的结构、权重等信息
new_model = keras.models.load_model('model.h5')

checkpoints 模式

提示

在网络上搜索 checkpoints 模式会发现多个不同的代码实现,可能是不同版本的 TensorFlow 接口不同。这里我使用的是的 keras 版本 3.1.1。

checkpoint 模式是最常见的一种保存方式,尽可能多地保存模型能帮助我们不错过效果最好的模型,但是实际操作也要考虑内存大小和运行效率。工程师的通用做法是每训练多少步后就在验证集上计算一次准确率,如果本次结果比上次好则保存新的模型。最常见的做法是直接每训练多少步就直接保存一次模型,实际上 TensorFlow 的 API 也提供了在模型文件名提供添加训练 step 后缀的方式。

保存模型

from keras.callbacks import ModelCheckpoint

#在开始训练之前,使用 Keras Model.compile 配置和编译模型。将 optimizer 类设置为 adam,将 loss 设置为您之前定义的 loss_fn 函数,并通过将 metrics 参数设置为 accuracy 来指定要为模型评估的指标。
model.compile(optimizer='adam',
              loss=loss_fn,
              metrics=['accuracy'])

#checkpoints检查点
filepath = "checkpoint_{epoch:02d}.keras"
#monitor='val_accuracy'与model.compile方法中的metrics相关联
checkpoint = ModelCheckpoint(filepath, monitor='val_accuracy', verbose=0)

#训练并评估模型
#使用 Model.fit 方法调整您的模型参数并最小化损失:
model.fit(x_train, y_train, epochs=10, callbacks=[checkpoint])

在上面的代码中,重点是 ModelCheckpoint 类,“回调以保存某个频率下的 Keras 模型或模型权重。”ModelCheckpoint中 callback 与使用model.fit()的训练结合使用,以在某个时间间隔保存模型或权重(在检查点文件中),因此可以稍后加载模型或权重,以从保存的状态继续训练。简单点理解就是在训练模型的过程中保存检查点位置的模型信息。

ModelCheckpoint 类构造方法如下:

#你需要比对一下跟你的keras版本中代码是否相同
def __init__(
    self,
    filepath,
    monitor="val_loss",
    verbose=0,
    save_best_only=False,
    save_weights_only=False,
    mode="auto",
    save_freq="epoch",
    initial_value_threshold=None,
)

  • filepath

字符串或格式类字符串,保存模型文件的路径,filepath 可以包含命名格式选项,这些选项将填充epoch的值和logs中的键(传入on_ech_end)。当save_weights_only=True时,filepath名称需要以“.weights.h5”结尾,或者当检查点保存整个模型时,应以“.keras”结尾(默认值)。例如:如果filepath“{epoch:02d}-{val_loss:.2f}.keras”,则模型检查点将与 epoch 编号和验证丢失一起保存在文件名中。文件路径的目录不应被任何其他回调重用,以避免冲突。

  • monitor

要监视的度量值名称。通常,度量是通过“Model.compile”方法设置的。例如上面代码中 val_accuracy。

  • verbose

详细模式,0 或 1。模式 0 是静默的,模式 1 在回调执行操作时显示消息。

  • save_best_only

如果“save_best_only=True”,则仅当模型被视为“最佳”时进行保存,并且根据监测的数量,最新的最佳模型不会被覆盖。如果“filepath”不包含像“{epoch}”这样的格式化选项,那么“文件路径”将被每个新的更好的模型覆盖。

  • save_weights_only

如果为“True”,则只保存模型的权重(model.save_weights(filepath)),否则保存整个模型(model.seave(filepath))。

  • mode

{autominmax}之一。如果“save_best_only=True”,则覆盖当前保存文件的决定是基于监控数量的最大化或最小化。对于val_acc,它应该是max,对于val_loss,它应是min等。在auto模式中,如果监测的量是acc或以fmeasure开始,则模式设置为max,其余量设置为min

  • save_freq

epoch或整数。当使用“epoch”时,回调会在每个 epoch 之后保存模型。当使用 integer 时,回调会在这么多批处理结束时保存模型。如果“模型”是用“steps_per_execution=N”编译的,则每 N 批都会检查保存条件。请注意,如果保存与历元不一致,则监控的度量可能不太可靠(它可能只反映一个批次,因为每个历元都会重置度量)。默认为“epoch”。

  • initial_value_threshold

要监视的度量的浮点初始“最佳”值。仅当“save_best_value=True”时适用。仅当当前模型的性能优于此值时,才会覆盖已保存的模型权重。

加载模型

未完待续

上次编辑于: