How to export a Keras model as a SavedModel

TensorFlow runtimes consume SavedModel directories as callable inference artifacts rather than editable Keras projects. Exporting a trained model after the architecture and weights are ready lets TensorFlow Serving, tf.saved_model.load(), and other TensorFlow consumers run the model without rebuilding the training code.

In Keras 3, model.export() is the supported path for SavedModel export. model.save() belongs to native .keras or legacy .h5 model files, while format="tf_saved_model" writes a SavedModel directory with callable endpoints.

Use the native .keras format when the artifact needs to keep Keras training configuration for continued editing or fine-tuning. Use SavedModel export when the serving input shape and dtype are ready to hand off, then reload the artifact and call serve before moving it into a serving runtime.

Steps to export a Keras model as a SavedModel:

  1. Install Keras and TensorFlow in the active Python environment.
    $ python -m pip install --upgrade keras tensorflow
  2. Select the TensorFlow backend before importing Keras.
    $ export KERAS_BACKEND=tensorflow

    Keras reads KERAS_BACKEND during import. Set it in the shell, notebook kernel, or process environment before any import keras statement.
    Related: How to set the Keras backend

  3. Create the export script.
    export_savedmodel.py
    import os
    import shutil
    from pathlib import Path
     
    os.environ.setdefault("KERAS_BACKEND", "tensorflow")
    os.environ.setdefault("TF_CPP_MIN_LOG_LEVEL", "2")
     
    import keras
    import numpy as np
    import tensorflow as tf
     
     
    export_dir = Path("credit-risk-score-savedmodel")
    if export_dir.exists():
        shutil.rmtree(export_dir)
     
    keras.utils.set_random_seed(42)
     
    model = keras.Sequential(
        [
            keras.Input(shape=(4,), name="features"),
            keras.layers.Dense(3, activation="relu", name="hidden"),
            keras.layers.Dense(2, activation="softmax", name="risk_score"),
        ]
    )
     
    sample = np.array([[0.2, 0.4, 0.1, 0.8]], dtype="float32")
    keras_output = model(sample, training=False).numpy()
     
    model.export(export_dir, format="tf_saved_model", verbose=False)
     
    reloaded = tf.saved_model.load(export_dir)
    served_output = reloaded.serve(tf.constant(sample)).numpy()
    prediction = [round(float(value), 4) for value in served_output[0]]
    artifact_files = sorted(path.name for path in export_dir.iterdir())
    signature_names = sorted(reloaded.signatures.keys())
     
    print(f"Exported SavedModel directory: {export_dir}")
    print(f"SavedModel files: {artifact_files}")
    print(f"Available signatures: {signature_names}")
    print("Serve endpoint: serve")
    print(f"Serve output shape: {served_output.shape}")
    print(f"Prediction row: {prediction}")
    print(f"Matches Keras output: {np.allclose(keras_output, served_output, atol=1e-6)}")

    Replace the demo model and sample tensor with the trained model and input shape used by the TensorFlow runtime that will load the SavedModel.

  4. Run the export script.
    $ python export_savedmodel.py
    Exported SavedModel directory: credit-risk-score-savedmodel
    SavedModel files: ['assets', 'fingerprint.pb', 'saved_model.pb', 'variables']
    Available signatures: ['serve', 'serving_default']
    Serve endpoint: serve
    Serve output shape: (1, 2)
    Prediction row: [0.6928, 0.3072]
    Matches Keras output: True

    A True value means the SavedModel reloaded through tf.saved_model.load() and the exported serve endpoint returned the same prediction as the original Keras model for the sample tensor.

  5. Verify the exported artifact from the script output.

    The directory should contain saved_model.pb and variables, the signatures should include serve, and the final line should read Matches Keras output: True.