Keras是一个用于深度学习的简单而强大的Python库。
鉴于深度学习模型可能需要数小时、数天甚至数周的时间来训练,因此知道如何从磁盘上保存和加载它们是很重要的。
在这篇文章中,你将发现如何将你的Keras模型保存到文件中,并再次加载它们以进行预测。
阅读本教程后,你将知道:
- 如何在不同的文件中保存模型权重和模型架构。
- 如何以YAML和JSON格式保存模型架构。
- 如何将模型权重和架构保存在一个文件中供以后使用。
让我们开始吧:
- 2017年3月更新:增加了先安装h5py的说明。
- 2017年3月更新:针对Keras API的变化更新了示例。
- 2018年3月更新:添加了下载数据集的备用链接。
- 2019年5月更新:添加了关于将模型保存和加载到单个文件的部分。
- Update Sep/2019:添加了关于使用PyYAML版本5的说明。
- 2022年6月更新:添加了关于废弃YAML格式的说明,并添加了关于协议缓冲区的部分。

如何保存和加载你的Keras深度学习模型
图片来源:art_inthecity,保留部分权利。
教程概述
如果你是Keras或深度学习的新手,请看这个分步骤的Keras教程。
Keras将保存你的模型架构和保存你的模型权重这两个问题分开。
模型权重被保存为HDF5格式。这是一种网格格式,是存储多维数字数组的理想选择。
模型结构可以用两种不同的格式来描述和保存。JSON和YAML。
在这篇文章中,我们要看三个保存和加载你的模型到文件的例子:
- 保存模型到JSON
- 保存模型到YAML
- 保存模型到HDF5
前两个例子分别保存模型结构和权重。在所有情况下,模型权重都被保存到HDF5格式文件中。
这些例子将使用相同的简单网络,在皮马印第安人的糖尿病发病二元分类数据集上训练。这是一个小型数据集,包含所有的数字数据,很容易操作。你可以下载这个数据集,并把它放在你的工作目录中,文件名为 "pima-indians-diabetes.csv"(更新:从这里下载)。
确认你已经安装了TensorFlow v2.x(例如,截至2022年6月的v2.9)。
注意:保存模型需要你安装了h5py库。它通常是作为TensorFlow的依赖项来安装的。你也可以按照下面的方法轻松安装它。
sudo pip install h5py
将你的神经网络模型保存为JSON格式
JSON是一种简单的文件格式,用于分层描述数据。
Keras通过to_json()函数提供了使用JSON格式描述任何模型的能力。这可以保存到文件中,之后通过*model_from_json()*函数加载,该函数将从JSON规范中创建一个新模型。
使用save_weights()函数可以直接从模型中保存权重,随后使用对称的load_weights()函数加载。
下面的例子在Pima Indians的数据集上训练和评估了一个简单的模型。然后,该模型被转换为JSON格式,并写入本地目录中的model.json。网络权重被写入本地目录下的model.h5。
模型和权重数据从保存的文件中加载,并创建一个新的模型。在使用之前,编译加载的模型是很重要的。这是为了使使用该模型进行的预测能够使用来自Keras后端适当的有效计算。
该模型以同样的方式进行评估,打印同样的评估分数。
# MLP for Pima Indians Dataset Serialize to JSON and HDF5
from tensorflow.keras.models import Sequential, model_from_json
from tensorflow.keras.layers import Dense
import numpy
import os
# fix random seed for reproducibility
numpy.random.seed(7)
# load pima indians dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# create model
model = Sequential()
model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# Fit the model
model.fit(X, Y, epochs=150, batch_size=10, verbose=0)
# evaluate the model
scores = model.evaluate(X, Y, verbose=0)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
# serialize model to JSON
model_json = model.to_json()
with open("model.json", "w") as json_file:
json_file.write(model_json)
# serialize weights to HDF5
model.save_weights("model.h5")
print("Saved model to disk")
# later...
# load json and create model
json_file = open('model.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
# load weights into new model
loaded_model.load_weights("model.h5")
print("Loaded model from disk")
# evaluate loaded model on test data
loaded_model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
score = loaded_model.evaluate(X, Y, verbose=0)
print("%s: %.2f%%" % (loaded_model.metrics_names[1], score[1]*100))
注意:鉴于算法或评估程序的随机性,或数字精度的差异,你的结果可能会有所不同。考虑多运行几次这个例子,并比较平均结果。
运行这个例子提供了下面的输出:
acc: 78.78%
Saved model to disk
Loaded model from disk
acc: 78.78%
该模型的JSON格式看起来如下:
{
"class_name":"Sequential",
"config":{
"name":"sequential_1",
"layers":[
{
"class_name":"Dense",
"config":{
"name":"dense_1",
"trainable":true,
"batch_input_shape":[
null,
8
],
"dtype":"float32",
"units":12,
"activation":"relu",
"use_bias":true,
"kernel_initializer":{
"class_name":"VarianceScaling",
"config":{
"scale":1.0,
"mode":"fan_avg",
"distribution":"uniform",
"seed":null
}
},
"bias_initializer":{
"class_name":"Zeros",
"config":{
}
},
"kernel_regularizer":null,
"bias_regularizer":null,
"activity_regularizer":null,
"kernel_constraint":null,
"bias_constraint":null
}
},
{
"class_name":"Dense",
"config":{
"name":"dense_2",
"trainable":true,
"dtype":"float32",
"units":8,
"activation":"relu",
"use_bias":true,
"kernel_initializer":{
"class_name":"VarianceScaling",
"config":{
"scale":1.0,
"mode":"fan_avg",
"distribution":"uniform",
"seed":null
}
},
"bias_initializer":{
"class_name":"Zeros",
"config":{
}
},
"kernel_regularizer":null,
"bias_regularizer":null,
"activity_regularizer":null,
"kernel_constraint":null,
"bias_constraint":null
}
},
{
"class_name":"Dense",
"config":{
"name":"dense_3",
"trainable":true,
"dtype":"float32",
"units":1,
"activation":"sigmoid",
"use_bias":true,
"kernel_initializer":{
"class_name":"VarianceScaling",
"config":{
"scale":1.0,
"mode":"fan_avg",
"distribution":"uniform",
"seed":null
}
},
"bias_initializer":{
"class_name":"Zeros",
"config":{
}
},
"kernel_regularizer":null,
"bias_regularizer":null,
"activity_regularizer":null,
"kernel_constraint":null,
"bias_constraint":null
}
}
]
},
"keras_version":"2.2.5",
"backend":"tensorflow"
}
将你的神经网络模型保存为YAML
注意:这个方法只适用于TensorFlow 2.5或更早的版本。如果你在以后版本的TensorFlow中运行它,你会看到一个RuntimeError,消息是 "由于任意代码执行的安全风险,方法model.to_yaml() 已经被删除。请使用model.to_json() 代替。"
这个例子与上面的JSON例子基本相同,只是YAML格式被用于模型规范。
注意,这个例子假设你已经安装了PyYAML 5,比如说:
sudo pip install PyYAML
在这个例子中,模型是用YAML描述的,保存在文件model.yaml中,之后通过*model_from_yaml()*函数加载到一个新的模型。
权重的处理方式与上述HDF5格式的model.h5相同:
# MLP for Pima Indians Dataset serialize to YAML and HDF5
from tensorflow.keras.models import Sequential, model_from_yaml
from tensorflow.keras.layers import Dense
import numpy
import os
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load pima indians dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# create model
model = Sequential()
model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# Fit the model
model.fit(X, Y, epochs=150, batch_size=10, verbose=0)
# evaluate the model
scores = model.evaluate(X, Y, verbose=0)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
# serialize model to YAML
model_yaml = model.to_yaml()
with open("model.yaml", "w") as yaml_file:
yaml_file.write(model_yaml)
# serialize weights to HDF5
model.save_weights("model.h5")
print("Saved model to disk")
# later...
# load YAML and create model
yaml_file = open('model.yaml', 'r')
loaded_model_yaml = yaml_file.read()
yaml_file.close()
loaded_model = model_from_yaml(loaded_model_yaml)
# load weights into new model
loaded_model.load_weights("model.h5")
print("Loaded model from disk")
# evaluate loaded model on test data
loaded_model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
score = loaded_model.evaluate(X, Y, verbose=0)
print("%s: %.2f%%" % (loaded_model.metrics_names[1], score[1]*100))
注意:鉴于算法或评估程序的随机性,或者数字精度的差异,你的结果可能会有所不同。考虑运行该例子几次并比较平均结果。
运行该例子会显示以下输出:
acc: 78.78%
Saved model to disk
Loaded model from disk
acc: 78.78%
用YAML格式描述的模型看起来像下面这样:
backend: tensorflow
class_name: Sequential
config:
layers:
- class_name: Dense
config:
activation: relu
activity_regularizer: null
batch_input_shape: !!python/tuple
- null
- 8
bias_constraint: null
bias_initializer:
class_name: Zeros
config: {}
bias_regularizer: null
dtype: float32
kernel_constraint: null
kernel_initializer:
class_name: VarianceScaling
config:
distribution: uniform
mode: fan_avg
scale: 1.0
seed: null
kernel_regularizer: null
name: dense_1
trainable: true
units: 12
use_bias: true
- class_name: Dense
config:
activation: relu
activity_regularizer: null
bias_constraint: null
bias_initializer:
class_name: Zeros
config: {}
bias_regularizer: null
dtype: float32
kernel_constraint: null
kernel_initializer:
class_name: VarianceScaling
config:
distribution: uniform
mode: fan_avg
scale: 1.0
seed: null
kernel_regularizer: null
name: dense_2
trainable: true
units: 8
use_bias: true
- class_name: Dense
config:
activation: sigmoid
activity_regularizer: null
bias_constraint: null
bias_initializer:
class_name: Zeros
config: {}
bias_regularizer: null
dtype: float32
kernel_constraint: null
kernel_initializer:
class_name: VarianceScaling
config:
distribution: uniform
mode: fan_avg
scale: 1.0
seed: null
kernel_regularizer: null
name: dense_3
trainable: true
units: 1
use_bias: true
name: sequential_1
keras_version: 2.2.5
一起保存模型权重和架构
Keras还支持一个更简单的接口,将模型权重和模型架构一起保存到一个H5文件中。
以这种方式保存模型包括我们需要知道的关于模型的一切,包括。
- 模型权重。
- 模型架构。
- 模型编译细节(损失和度量)。
- 模型优化器状态。
这意味着我们可以直接加载和使用该模型,而不必像上面的例子那样重新编译。
注意:这是保存和加载你的Keras模型的首选方式。
如何保存Keras模型
你可以通过对模型调用*save()*函数并指定文件名来保存你的模型。
下面的例子通过首先拟合一个模型,评估它并将其保存到model.h5文件中来演示这一点。
# MLP for Pima Indians Dataset saved to single file
from numpy import loadtxt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
# load pima indians dataset
dataset = loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# define model
model = Sequential()
model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# Fit the model
model.fit(X, Y, epochs=150, batch_size=10, verbose=0)
# evaluate the model
scores = model.evaluate(X, Y, verbose=0)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
# save model and architecture to single file
model.save("model.h5")
print("Saved model to disk")
注意:鉴于算法或评估程序的随机性,或者数字精度的差异,你的结果可能会有所不同。考虑多运行几次这个例子,并比较平均结果。
运行这个例子可以拟合模型,总结模型在训练数据集上的表现并将模型保存到文件中:
acc: 77.73%
Saved model to disk
我们以后可以从文件中加载这个模型并使用它。
请注意,在Keras库中,有另一个函数做同样的事情,如下所示。
...
# equivalent to: model.save("model.h5")
from tensorflow.keras.models import save_model
save_model(model, "model.h5")
如何加载一个Keras模型
然后,你保存的模型可以通过调用load_model() 函数并传递文件名来加载。该函数返回具有相同架构和权重的模型。
在这种情况下,我们加载模型,总结架构,并在同一数据集上评估,以确认权重和架构是相同的。
# load and evaluate a saved model
from numpy import loadtxt
from tensorflow.keras.models import load_model
# load model
model = load_model('model.h5')
# summarize model.
model.summary()
# load dataset
dataset = loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# evaluate the model
score = model.evaluate(X, Y, verbose=0)
print("%s: %.2f%%" % (model.metrics_names[1], score[1]*100))
运行这个例子,首先加载模型,打印出模型结构的摘要,然后在同一数据集上评估加载的模型。
注意:鉴于算法或评估程序的随机性,或数字精度的差异,你的结果可能会有所不同。考虑将这个例子运行几次,并比较平均结果。
该模型实现了相同的准确度得分,在这种情况下是77%。
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 12) 108
_________________________________________________________________
dense_2 (Dense) (None, 8) 104
_________________________________________________________________
dense_3 (Dense) (None, 1) 9
=================================================================
Total params: 221
Trainable params: 221
Non-trainable params: 0
_________________________________________________________________
acc: 77.73%
协议缓冲区格式
虽然使用HDF5格式保存和加载Keras模型是推荐的方式,但TensorFlow支持另一种格式,即*协议缓冲区*。人们认为保存和加载协议缓冲区格式更快,但这样做会产生多个文件。语法是一样的,只是我们不需要为文件名提供.h5 的扩展名:
# save model and architecture to single file
model.save("model")
# ... later
# load model
model = load_model('model')
# print summary
model.summary()
这些将创建一个有以下文件的目录 "model":
model/
|-- assets/
|-- keras_metadata.pb
|-- saved_model.pb
`-- variables/
|-- variables.data-00000-of-00001
`-- variables.index
这也是我们在TensorFlow v1.x中用来保存模型的格式,当你从TensorFlow Hub下载预训练的模型时可能会遇到这种情况。
进一步阅读
- 如何保存Keras模型?在Keras文档中。
- 关于Keras模型在Keras文档中。
总结
在这篇文章中,你发现了如何序列化你的Keras深度学习模型。
你学会了如何将你训练好的模型保存到文件中,然后再加载它们,用它们来进行预测。
你还了解到,模型的权重很容易用HDF5格式存储,网络结构可以用JSON或YAML格式保存。
你对保存你的深度学习模型或对这篇文章有什么问题吗?
在评论中提出你的问题,我将尽力回答。