本文正在参加「金石计划 . 分割6万现金大奖」

前语

本文主要运用 cpu 版别的 tensorflow-2.1 来完成深度学习权重参数/模型的保存和加载操作。

在咱们进行项目期间,很多时候都要在模型练习期间、练习完毕之后对模型或许模型权重进行保存,然后咱们能够从之前停止的当地恢恢复模型作用继续进行练习或许直接投入实际运用,别的为了节约存储空间咱们还能够自界说保存内容和保存频率。

文本纲要

  1. 读取数据
  2. 建立深度学习模型
  3. 运用回调函数在每个 epoch 后主动保存模型权重
  4. 运用回调函数每经过 5 个 epoch 对模型权重保存一次
  5. 手动保存模型权重到指定目录
  6. 手动保存整个模型结构和权重

实现办法

1. 读取数据

(1)本文要点介绍模型或许模型权重的保存和读取的相关操作,运用到的是 MNIST 数据集仅是为了演示作用,咱们无需关心模型练习的质量好坏。

(2)这儿是惯例的读取数据操作,咱们为了能较快介绍本文要点内容,只运用了 MNIST 前 1000 条数据,然后对数据进行归一化操作,加快模型练习收敛速度,而且将每张图片的数据从二维压缩成一维。

import os
import tensorflow as tf
from tensorflow import keras
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()
train_labels = train_labels[:1000]
test_labels = test_labels[:1000]
train_images = train_images[:1000].reshape(-1, 28 * 28) / 255.0
test_images = test_images[:1000].reshape(-1, 28 * 28) / 255.0

2. 建立深度学习模型

(1)这儿主要是建立一个最简单的深度学习模型。

(2)第一层将图片的长度为 784 的一维向量转换成 256 维向量的全衔接操作,而且用到了 relu 激活函数。

(3)第二层紧接着运用了防止过拟合的 Dropout 操作,神经元丢掉率为 50% 。

(4)第三层为输出层,也就是输出每张图片属于对应 10 种类别的散布概率。

(5)优化器咱们选择了最常见的 Adam 。

(6)丢失函数选择了 SparseCategoricalCrossentropy 。

(7)评价目标选用了 SparseCategoricalAccuracy 。

def create_model():
    model = tf.keras.Sequential([keras.layers.Dense(256, activation='relu', input_shape=(784,)),
                                 keras.layers.Dropout(0.5),
                                 keras.layers.Dense(10) ])
    model.compile(optimizer='adam',
                  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                  metrics=[tf.keras.metrics.SparseCategoricalAccuracy()])
    return model

3. 运用回调函数在每个 epoch 后主动保存模型权重

(1)这儿介绍一种在模型练习期间保存权重参数的办法,咱们界说一个回调函数 callback ,它能够在练习过程中将权重保存在自界说目录中 weights_path ,在练习过程中总共履行 5 次 epoch ,每次 epoch 完毕之后就会保存一次模型的权重到指定的目录。

(2)能够看到最终运用测验集进行评价的 loss 为 0.4952 ,分类准确率为 0.8500 。

weights_path = "training_weights/cp.ckpt"
weights_dir = os.path.dirname(weights_path)
callback = tf.keras.callbacks.ModelCheckpoint(filepath=weights_path, save_weights_only=True,  verbose=1)
model = create_model()
model.fit(train_images, 
          train_labels,  
          epochs=5,
          validation_data=(test_images, test_labels),
          callbacks=[callback]) 

输出成果为:

 val_loss: 0.4952 - val_sparse_categorical_accuracy: 0.8500

(3)咱们阅读目标文件夹里,只要三个文件,每个 epoch 后主动都会保存三个文件,在下一次 epoch 之后会主动更新这三个文件的内容。

os.listdir(weights_dir)

成果为:

['checkpoint', 'cp.ckpt.data-00000-of-00001', 'cp.ckpt.index']

(4) 咱们经过 create_model 界说了一个新的模型实例,然后让其在没有练习的情况下运用测验数据进行评价,成果可想而知,准确率差的离谱。

NewModel = create_model()
loss, acc = NewModel.evaluate(test_images, test_labels, verbose=2)

成果为:

loss: 2.3694 - sparse_categorical_accuracy: 0.1330

(5) tensorflow 中只要两个模型有相同的模型结构,就能够在它们之间共享权重,所以咱们运用 NewModel 读取了之前练习好的模型权重,再运用测验集对其进行评价发现,丢失值和准确率和旧模型的成果彻底相同,阐明权重被相同结构的新模型成功加载并运用。

NewModel.load_weights(checkpoint_path)
loss, acc = NewModel.evaluate(test_images, test_labels, verbose=2)

输出成果:

loss: 0.4952 - sparse_categorical_accuracy: 0.8500

4. 运用回调函数每经过 5 个 epoch 对模型权重保存一次

(1)如果咱们想保留多个中心 epoch 的模型练习的权重,或许咱们想每隔几个 epoch 保存一次模型练习的权重,这时候咱们能够经过设置保存频率 period 来完成,我这儿让新建的模型练习 30 个 epoch ,在每经过 10 epoch 后保存一次模型练习好的权重。

(2)运用测验集对此次模型进行评价,丢失值为 0.4047 ,准确率为 0.8680 。

weights_path = "training_weights2/cp-{epoch:04d}.ckpt"
weights_dir = os.path.dirname(weights_path)
batch_size = 64
cp_callback = tf.keras.callbacks.ModelCheckpoint( filepath=weights_path, 
                                                  verbose=1, 
                                                  save_weights_only=True,
                                                  period=10)
model = create_model()
model.save_weights(weights_path.format(epoch=1))
model.fit(train_images, 
          train_labels,
          epochs=30, 
          batch_size=batch_size, 
          callbacks=[cp_callback],
          validation_data=(test_images, test_labels),
          verbose=1)

成果输出为:

val_loss: 0.4047 - val_sparse_categorical_accuracy: 0.8680   

(2)这儿咱们能看到指定目录中的文件组成,这儿的 0001 是因为练习时指定了要保存的 epoch 的权重,其他都是每 10 个 epoch 保存的权重参数文件。目录中有一个 checkpoint ,它是一个检查点文本文件,文件保存了一个目录下所有的模型文件列表,首行记载的是最终(最近)一次保存的模型称号。

(3)每个 epoch 保存下来的文件都包括:

  • 一个索引文件,指示哪些权重存储在哪个分片中

  • 一个或多个包括模型权重的分片

阅读文件夹内容

os.listdir(weights_dir)

成果如下:

['checkpoint', 'cp-0001.ckpt.data-00000-of-00001', 'cp-0001.ckpt.index', 'cp-0010.ckpt.data-00000-of-00001', 'cp-0010.ckpt.index', 'cp-0020.ckpt.data-00000-of-00001', 'cp-0020.ckpt.index', 'cp-0030.ckpt.data-00000-of-00001', 'cp-0030.ckpt.index']

(4)咱们将最终一次保存的权重读取出来,然后创立一个新的模型去读取刚刚保存的最新的之前练习好的模型权重,然后经过测验集对新模型进行评价,发现丢失值准确率和之前彻底相同,阐明权重被成功读取并运用。

latest = tf.train.latest_checkpoint(weights_dir)
newModel = create_model()
newModel.load_weights(latest)
loss, acc = newModel.evaluate(test_images, test_labels, verbose=2)

成果如下:

loss: 0.4047 - sparse_categorical_accuracy: 0.8680

5. 手动保存模型权重到指定目录

(1)有时候咱们还想手动将模型练习好的权重保存到指定的目录下,咱们能够运用 save_weights 函数,经过咱们新建了一个相同的新模型,然后运用 load_weights 函数去读取权重并运用测验集对其进行评价,发现丢失值和准确率仍然和之前的两种成果彻底相同。

model.save_weights('./training_weights3/my_cp')
newModel = create_model()
newModel.load_weights('./training_weights3/my_cp')
loss, acc = newModel.evaluate(test_images, test_labels, verbose=2)

成果如下:

loss: 0.4047 - sparse_categorical_accuracy: 0.8680

6. 手动保存整个模型结构和权重

(1)有时候咱们还需要保存整个模型的结构和权重,这时候咱们直接运用 save 函数即可将这些内容保存到指定目录,运用该办法要保证目录是存在的不然会报错,所以这儿咱们要创立文件夹。咱们能看到丢失值为 0.4821,准确率为 0.8460 。

model = create_model()
model.fit(train_images, train_labels, epochs=5, validation_data=(test_images, test_labels), verbose=1)
!mkdir my_model
modelPath = './my_model'
model.save(modelPath)

输出成果:

val_loss: 0.4821 - val_sparse_categorical_accuracy: 0.8460

(2)然后咱们经过函数 load_model 即可生成出一个新的彻底相同结构和权重的模型,咱们运用测验集对其进行评价,发现准确率和丢失值和之前彻底相同,阐明模型结构和权重被彻底读取恢复。

new_model = tf.keras.models.load_model(modelPath)
loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)

输出成果:

 loss: 0.4821 - sparse_categorical_accuracy: 0.8460