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:
- How to save model weights and architecture in different files.
- How to save model architecture in YAML and JSON formats.
- 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:
- Save Model to JSON.
- Save Model to YAML.
- 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:
- Model weights.
- Model architecture.
- Model compilation details (loss and metrics).
- 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