Saving and Loading Keras Deep Learning Model Tutorial

Keras is a simple and powerful Python deep learning library.

Given that deep learning, models can take hours, days, or even weeks to train, knowing how to save and load them from disc is essential.

In this post, you’ll learn how to save your Keras models to a file and then load them again to make predictions.

After reading this tutorial, you will understand:

  1. How to save model weights and architecture in different files.
  2. How to save model architecture in YAML and JSON formats.
  3. How to combine model weights and architecture into a single file for future use.

Tutorial Overview

See this step-by-step Keras tutorial if you’re new to Keras or deep learning.

Keras distinguishes between saving your model architecture and saving your model weights.

The weights of the models are saved in HDF5 format. This is a grid format for storing multi-dimensional numerical arrays.

JSON and YAML are the two formats that can be used to describe and save the model structure.

In this post, we’ll look at three different ways to save and load your model to a file:

  1. Save Model to JSON.
  2. Save Model to YAML.
  3. Save Model to HDF5.

The model architecture and weights are saved separately in the first two examples. In all cases, the model weights are saved in an HDF5 format file.

The examples will all use the same simple network that was trained on the Pima Indians’ diabetes onset binary classification dataset. This is a small dataset with all numerical data that is simple to work with. You can download this dataset and save it as “pima-indians-diabetes.csv” in your working directory.

Verify that TensorFlow v2.x is installed (e.g. v2.9 as of June 2022).

It is important to note that saving models necessitate the installation of the h5py library. It is typically installed as a dependency alongside TensorFlow. You can also easily install it as follows:

sudo pip install h5py

Save Your Neural Network Model to JSON

JSON is a simple file format for hierarchically describing data.

Keras provides the ability to describe any model using JSON format with a to_json() function. This can be saved to file and later loaded via the model_from_json() function that will create a new model from the JSON specification.

The weights are saved from the model directly using the save_weights() function and then loaded using the symmetrical load_weights() function.

The example below trains and evaluates a simple model on the Pima Indians dataset. The model is then converted to JSON format and written to model.json in the local directory. The network weights are written to model.h5 in the local directory.

A new model is created after loading the model and weight data from the saved files. It is critical to compile the loaded model before using it. This is done so that model predictions can use the most efficient computation from the Keras backend.

The model is evaluated in the same manner, with the same evaluation score printed.

# 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))

Note: Because the algorithm or evaluation procedure is stochastic, your results may differ due to differences in numerical precision. Consider running the example several times and comparing the average result.

Running this example yields the results shown below.

acc: 78.78%
Saved model to disk
Loaded model from disk
acc: 78.78%

The model’s JSON format appears to be as follows:

{ 
"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"
}

Save Your Neural Network Model to YAML

Note: This method is only applicable to TensorFlow 2.5 and earlier. If you run it in a later version of TensorFlow, you’ll get a RuntimeError with the message “Method model.to_yaml() has been removed due to the security risk of arbitrary code execution.” Instead, please use model.to_json().”

This example is similar to the previous JSON example, except the model specification is in YAML format.

Please keep in mind that this example assumes you have PyYAML 5 installed, for example:

sudo pip install PyYAML

The model is described in YAML in this example, saved to the file model.yaml, and then loaded into a new model using the model_from_yaml() function.

Weights are handled in the same way as above in HDF5 format as 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))

Note: Because the algorithm or evaluation procedure is stochastic, your results may differ due to differences in numerical precision. Consider running the example several times and comparing the average result.

Running the example yields the following results.

acc: 78.78%
Saved model to disk
Loaded model from disk
acc: 78.78%

The model described in YAML format is as follows:

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

Save Model Weights and Architecture Together

Keras also has a simpler interface for saving both the model weights and the model architecture in a single H5 file.

This method of saving the model includes everything we need to know about the model, including:

  1. Model weights.
  2. Model architecture.
  3. Model compilation details (loss and metrics).
  4. Model optimizer state.

This means we can load and use the model without having to recompile it as we did in the previous examples.

Note: Please keep in mind that this is the preferred method for saving and loading your Keras model.

How to Save a Keras Model

You can save your model by invoking the save() function and specifying a filename.

The following example shows this by first fitting a model, evaluating it, and saving it to the file 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")

Note: Because the algorithm or evaluation procedure is stochastic, your results may differ due to differences in numerical precision. Consider running the example several times and comparing the average result.

When you run the example, it will fit the model, summarize its performance on the training dataset, and save the model to file.

acc: 77.73%
Saved model to disk

We can then load and use this model from the file.

It should be noted that there is another function in the Keras library that does the same thing, as follows:

...
# equivalent to: model.save("model.h5")
from tensorflow.keras.models import save_model
save_model(model, "model.h5")

How to Load a Keras Model

Your saved model can then be loaded later by passing the filename to the load_model() function. The model with the same architecture and weights is returned by the function.

In this case, we load the model, summarize the architecture, and test it on the same dataset to ensure that the weights and architecture are identical.

# 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))

Running the example loads the model, prints a summary of its architecture, and then evaluates it on the same dataset.

Note: Because the algorithm or evaluation procedure is stochastic, your results may differ due to differences in numerical precision. Consider running the example several times and comparing the average result.

The model achieves the same accuracy score, which is 77 percent in this case.

_________________________________________________________________
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%

Protocol Buffer Format

While saving and loading a Keras model in HDF5 format is recommended, TensorFlow also supports a protocol buffer format. It is faster to save and load a protocol buffer format, but this results in multiple files. The syntax is the same, except that the.h5 extension is not required in the filename:

# save model and architecture to single file
model.save("model")

# ... later

# load model
model = load_model('model')
# print summary
model.summary()

These will generate the directory “model” containing the following files:

model/
|-- assets/
|-- keras_metadata.pb
|-- saved_model.pb
`-- variables/
|-- variables.data-00000-of-00001
`-- variables.index

This is also the format in which TensorFlow v1.x models were saved. This may occur if you download a pretrained model from TensorFlow Hub.

Summary

You learned how to serialize Keras deep learning models in this post.

You learned how to save your trained models to files and then load them up to make predictions.

You also discovered that model weights can be easily saved in HDF5 format and that network structure can be saved in JSON or YAML format.

Source link