A trained Keras model often needs to move from a notebook or training script into another Python process before it can be scored, evaluated, or shared with a teammate. Saving the complete model to the native .keras format keeps the architecture and learned weights together instead of relying on a separate model-building script.

The native Keras file is the standard whole-model artifact for Keras 3. It can store the model configuration, layer weights, and compile information, including optimizer state when the optimizer has been built during training.

Use native .keras saving when the next consumer is another Keras process that should reload the same model for prediction, evaluation, or fine-tuning. Use a SavedModel export when the target is TensorFlow serving tooling, and handle custom-layer registration separately when the model contains custom Python objects.

Steps to save and load a Keras model:

  1. Install Keras and the backend package used by the model.
    $ python -m pip install --upgrade keras jax

    The sample script uses JAX. Use the same backend package and runtime that the saved model will run with.

  2. Select the backend before importing Keras.
    $ export KERAS_BACKEND=jax

    Keras reads KERAS_BACKEND during import, so set it before opening a Python shell, notebook kernel, or script process.
    Related: How to set the Keras backend

  3. Create the save and load test script.
    save_load_model.py
    import os
    from pathlib import Path
     
    os.environ.setdefault("KERAS_BACKEND", "jax")
     
    import keras
    import numpy as np
     
     
    keras.utils.set_random_seed(42)
     
    model_path = Path("credit-risk-score.keras")
    if model_path.exists():
        model_path.unlink()
     
    x_train = np.linspace(0.05, 0.95, 32, dtype="float32").reshape(8, 4)
    y_train = ((x_train[:, 0] + x_train[:, 1]) > 0.9).astype("float32").reshape(-1, 1)
     
    model = keras.Sequential(
        [
            keras.Input(shape=(4,), name="features"),
            keras.layers.Dense(6, activation="relu", name="hidden"),
            keras.layers.Dense(1, activation="sigmoid", name="risk_score"),
        ]
    )
    model.compile(
        optimizer=keras.optimizers.Adam(learning_rate=0.05),
        loss=keras.losses.BinaryCrossentropy(),
        metrics=[keras.metrics.BinaryAccuracy(name="accuracy")],
    )
    model.fit(x_train, y_train, epochs=8, batch_size=4, verbose=0)
     
    sample = np.array([[0.25, 0.60, 0.35, 0.45]], dtype="float32")
    before_save = model.predict(sample, verbose=0)
     
    model.save(model_path)
    loaded_model = keras.models.load_model(model_path)
    after_load = loaded_model.predict(sample, verbose=0)
    loaded_loss, loaded_accuracy = loaded_model.evaluate(x_train, y_train, verbose=0)
     
    print(f"Backend: {keras.backend.backend()}")
    print(f"Saved model: {model_path}")
    print(f"Saved file exists: {model_path.exists()}")
    print(f"Loaded model type: {loaded_model.__class__.__name__}")
    print(f"Loaded optimizer: {loaded_model.optimizer.__class__.__name__}")
    print(f"Reloaded accuracy: {loaded_accuracy:.4f}")
    print(f"Prediction before save: {before_save[0, 0]:.6f}")
    print(f"Prediction after load: {after_load[0, 0]:.6f}")
    print(f"Predictions match: {np.allclose(before_save, after_load, atol=1e-6)}")

    Replace the demo training data and model definition with the trained model that should become the portable .keras artifact.

  4. Run the script.
    $ python save_load_model.py
    Backend: jax
    Saved model: credit-risk-score.keras
    Saved file exists: True
    Loaded model type: Sequential
    Loaded optimizer: Adam
    Reloaded accuracy: 0.6250
    Prediction before save: 0.595262
    Prediction after load: 0.595262
    Predictions match: True

    Predictions match: True confirms that keras.models.load_model() restored a model that returns the same prediction for the sample input.

  5. Remove the demo script and saved model if the run was only a save/load test.
    $ rm -f save_load_model.py credit-risk-score.keras

    Do not delete a production .keras artifact until it has been copied to the intended model registry, release directory, or deployment handoff location.