一图讲解
每次跟随教程进行深度学习模型训练过程中,都要把下载数据,搭建模型,训练模型,预测的过程走一遍,尤其是我们针对同一个数据进行不同方向学习的时候,我们要把一个相同的模型来回跑数次,大量的时间写重复的代码会极大的降低我们的学习积极性,那么如何将我们计算好的模型封装起来,下次遇到相同情况直接调用呢?下面我将结合tensorflow教程,详细的讲述这一过程。
一图讲解:
从上图可以看出来,我们要想省去重复计算模型的步骤,可以将中间的计算模型封装保存。
保存策略有两个:
1,仅封装权重、偏置,每次需要重新载入数据、建立相同框架结构模型,然后直接将权重参数加载进入模型,进行预测;对应函数为:tf.keras.callbacks.ModelCheckpoint()
2,封装整个模型,下次使用直接调用模型。对应函数为:model.save()
下面代码详细介绍存储过程
仅保存权重和偏置
代码借鉴自tensorflow官方教程
https://tensorflow.google.cn/tutorials/keras/save_and_load
导入tensorflow和依赖项
from __future__ import absolute_import, division, print_function, unicode_literals
import os
import tensorflow as tf
from tensorflow import keras
print(tf.__version__)
2.0.0
下载数据集
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()
train_labels = train_labels[:1000] #为了达到快速计算的目的,仅取前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
定义模型
#定义一个序列模型
def create_model():
model = tf.keras.models.Sequential([
keras.layers.Dense(512, activation = 'relu', input_shape=(784,)),
keras.layers.Dropout(0.2),
keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
#创建模型实例
model = create_model()
#显示模型结构
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense (Dense) (None, 512) 401920
_________________________________________________________________
dropout (Dropout) (None, 512) 0
_________________________________________________________________
dense_1 (Dense) (None, 10) 5130
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________
※※训练期间保持模型※※
创建一个只在训练期间保存权重的 tf.keras.callbacks.ModelCheckpoint 回调:
checkpoint_path = "Lee_1/cp.ckpt" #‘Lee_1’ 是建立在执行文件的相同文件目录下的文件夹,该命令将文件路径给到对象checkpoint_path
checkpoint_dir = os.path.dirname(checkpoint_path) #设定检测路径
#创建一个保存模型权重的回调,里面的参数包括:文件的存储路径,保存的数据种类,显示的内容
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path, save_weights_only = True,
verbose = 1)
#使用新的回调训练模型
model.fit(train_images,
train_labels,
epochs = 10,
validation_data = (test_images, test_labels),
callbacks = [cp_callback] #通过回调训练
# 这可能会生成与保存优化程序状态相关的警告。
# 这些警告(以及整个笔记本中的类似警告)是防止过时使用,可以忽略。
Train on 1000 samples, validate on 1000 samples
Epoch 1/10
832/1000 [=======================>......] - ETA: 0s - loss: 1.2203 - accuracy: 0.6370
Epoch 00001: saving model to Lee_1/cp.ckpt #Lee_1是新生成的文件夹,位于执行文件同一目录下
1000/1000 [==============================] - 1s 909us/sample - loss: 1.1273 - accuracy: 0.6700 - val_loss: 0.7261 - val_accuracy: 0.7830
Epoch 2/10
800/1000 [=======================>......] - ETA: 0s - loss: 0.4441 - accuracy: 0.8800
Epoch 00002: saving model to Lee_1/cp.ckpt
1000/1000 [==============================] - 0s 163us/sample - loss: 0.4224 - accuracy: 0.8860 - val_loss: 0.5240 - val_accuracy: 0.8370
Epoch 3/10
800/1000 [=======================>......] - ETA: 0s - loss: 0.2870 - accuracy: 0.9225
Epoch 00003: saving model to Lee_1/cp.ckpt
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
创建一个新的未经训练的模型。仅恢复模型的权重时,必须具有与原始模型具有相同网络结构的模型。由于模型具有相同的结构,您可以共享权重,尽管它是模型的不同实例。
现在重建一个新的未经训练的模型,并在测试集上进行评估。未经训练的模型将在机会水平(chance levels)上执行(准确度约为10%):
#创建模型
model = create_model() #这个文件时在jupyter note里面接续上面的指令继续建立的,因此可以直接创建文件
# 若新打开任务创建文件,首先需要重新导入数据,其次建立同样的网络结构,然后加载权重参数
#评估模型
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print('Untrained model, accuracy: {:5.2f}%'.format(100*acc))
1000/1 - 0s - loss: 2.4277 - accuracy: 0.0760
Untrained model, accuracy: 7.60%
现在从之前保存的checkpoint加载权重并重新评估
#加载权重
model.load_weights(checkpoint_path) #同上,这里加载了训练好的权重参数
#重新评估模型
loss, acc = model.evaluate(test_images, test_labels, verbose=2)
print('Untrained model, accuracy: {:5.2f}%'.format(100*acc))
1000/1 - 0s - loss: 0.4564 - accuracy: 0.8760
Restored model, accuracy: 87.60%
模型的保存方法
手动保存权重
#保存权重
model.save_weights('./checkpoints/my_checkpoint')
#创建模型
model = create_model()
#加载权重
model.load_weights('./checkpoint/my_checkpoint')
#评估模型
loss,acc = model.evaluate(test_images, test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
手动保存整个模型
Keras 可以使用 HDF5 标准提供基本保存格式。出于我们的目的,可以将保存的模型视为单个二进制blob:
#创建一个模型
model = create_model()
#训练模型
model.fit(train_images, train_labels, epoch = 5)
#将整个模型保存为HDF5文件
model.save('my_model.h5') #这里我将保持的文件移动到了'E:/个人文件/学习/文件读取/my_model.h5'
使用模型
#加载模型,相同模型,相同权重及优化方法
new_model = keras.models.load_model('E:/个人文件/学习/文件读取/my_model.h5')
#显示网络结构
new_model.summary()
Model: "sequential_5"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_10 (Dense) (None, 512) 401920
_________________________________________________________________
dropout_5 (Dropout) (None, 512) 0
_________________________________________________________________
dense_11 (Dense) (None, 10) 5130
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
评估
loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))
1000/1 - 0s - loss: 0.4956 - accuracy: 0.8640
Restored model, accuracy: 86.40%
这项技术可以保存一切:
权重
模型配置(结构)
优化器配置
Keras 通过检查网络结构来保存模型。目前,它无法保存 Tensorflow 优化器(调用自 tf.train)。使用这些的时候,您需要在加载后重新编译模型,否则您将失去优化器的状态。
tips
上面创建模型和加载模型的代码都是延续之前的代码继续编写,因此可以直接调用。若新建立任务,需要根据实际情况重新加载数据并创建网络结构(网络结构必须一样)