TensorFlow SavedModel Format

SavedModel is TensorFlow's universal format for saving a complete, self-contained model package. Unlike the Keras .keras format (which is Keras-specific), SavedModel works across every TensorFlow runtime — Python, C++, Java, JavaScript, mobile, and server-side REST APIs. A SavedModel contains the computation graph, the trained weights, and the serving signatures. Any system that understands TensorFlow can load and run it without the original training code.

What a SavedModel Contains

my_model/                      ← Root directory
├── saved_model.pb             ← Computation graph (Protocol Buffer format)
│                                 Contains the TF graph operations and
│                                 function signatures for serving
├── variables/
│   ├── variables.index        ← Index of variable names and locations
│   └── variables.data-00000  ← Actual weight values (can be multiple shards)
└── assets/                    ← Optional: vocab files, lookup tables, etc.

Saving a Model as SavedModel

import tensorflow as tf

# Save in SavedModel format
model.save('my_saved_model/')

# Equivalently with tf.saved_model
tf.saved_model.save(model, 'my_saved_model/')

Loading a SavedModel

# Load with tf.keras — returns a Keras model object
loaded_model = tf.keras.models.load_model('my_saved_model/')

# Make predictions
predictions = loaded_model.predict(x_test)
loaded_model.evaluate(x_test, y_test)

# Load with tf.saved_model — returns a lower-level SavedModel object
raw_model = tf.saved_model.load('my_saved_model/')

# Inspect serving signatures
print(list(raw_model.signatures.keys()))
# ['serving_default']

# Call the serving function directly
serving_fn = raw_model.signatures['serving_default']
result = serving_fn(input_1=tf.constant(x_test[:5]))
print(result)

Serving Signatures

A serving signature defines the input/output interface of the model when deployed. It tells the serving system exactly what tensor names and shapes to expect and what names and shapes to return.

# Inspect the serving signature
serving_fn = raw_model.signatures['serving_default']
print(serving_fn.structured_input_signature)
print(serving_fn.structured_outputs)

# Example output:
# Input:  {'input_1': TensorSpec(shape=(None, 224, 224, 3), dtype=tf.float32)}
# Output: {'output_0': TensorSpec(shape=(None, 10), dtype=tf.float32)}

Saving a Custom Serving Function

You can attach a custom serving function that handles preprocessing, so callers send raw inputs (like raw pixel values or raw text) instead of preprocessed tensors.

import tensorflow as tf

class ClassifierWithPreprocessing(tf.Module):
    def __init__(self, model):
        self.model = model

    @tf.function(input_signature=[
        tf.TensorSpec(shape=[None, None, None, 3], dtype=tf.uint8, name='image')
    ])
    def serve(self, image):
        # Preprocessing happens inside the serving function
        image = tf.cast(image, tf.float32) / 255.0
        image = tf.image.resize(image, [224, 224])
        return {'predictions': self.model(image, training=False)}

# Wrap and save
wrapper = ClassifierWithPreprocessing(model)
tf.saved_model.save(
    wrapper,
    'model_with_preprocessing/',
    signatures={'serving_default': wrapper.serve}
)
# At inference time, caller sends raw uint8 images
caller_model = tf.saved_model.load('model_with_preprocessing/')
raw_image = tf.constant(some_uint8_image[np.newaxis])   # (1, H, W, 3) uint8
result = caller_model.serve(image=raw_image)
print(result['predictions'])

SavedModel for TensorFlow Serving

TensorFlow Serving is a production server that loads SavedModels and serves predictions over a REST or gRPC API. It handles batching, versioning, and hardware acceleration automatically.

# Export versioned model for TF Serving
# TF Serving expects: model_name/version_number/
import os

MODEL_DIR = 'tf_serving/my_classifier'
VERSION = 1
export_path = os.path.join(MODEL_DIR, str(VERSION))
model.save(export_path)

# Directory structure:
# tf_serving/my_classifier/1/saved_model.pb
#                            1/variables/...

# Start TF Serving (Docker command):
# docker run -p 8501:8501 \
#   --mount type=bind,source=/path/to/tf_serving,target=/models \
#   -e MODEL_NAME=my_classifier \
#   tensorflow/serving

# Query via REST API:
import requests, json, numpy as np

payload = json.dumps({
    'instances': x_test[:5].tolist()
})
response = requests.post(
    'http://localhost:8501/v1/models/my_classifier:predict',
    data=payload
)
print(response.json())

Converting SavedModel to Other Formats

# Convert to TFLite for mobile
converter = tf.lite.TFLiteConverter.from_saved_model('my_saved_model/')
tflite_model = converter.convert()
with open('model.tflite', 'wb') as f:
    f.write(tflite_model)

# Convert to TensorFlow.js for browser
# (requires: pip install tensorflowjs)
# tensorflowjs_converter \
#   --input_format=tf_saved_model \
#   my_saved_model/ \
#   tfjs_model/

# Convert to ONNX for cross-framework compatibility
# (requires: pip install tf2onnx)
# python -m tf2onnx.convert \
#   --saved-model my_saved_model/ \
#   --output model.onnx

SavedModel vs Other Formats

Format          Extension    When to Use
──────────────────────────────────────────────────────────────────
SavedModel      directory    Production, TF Serving, cross-platform
.keras          .keras       Keras projects, training resumption
HDF5            .h5          Legacy projects, simple sharing
TFLite          .tflite      Mobile, embedded, edge deployment
TF.js           directory    Browser-based inference
ONNX            .onnx        Cross-framework (PyTorch ↔ TF)
──────────────────────────────────────────────────────────────────

Verifying a SavedModel

# Use the saved_model_cli tool to inspect without Python
# saved_model_cli show --dir my_saved_model/ --all

# In Python:
imported = tf.saved_model.load('my_saved_model/')
print(dir(imported))

# Check all callable functions
for name in dir(imported):
    attr = getattr(imported, name)
    if callable(attr):
        print(name, type(attr))

SavedModel is the production backbone of TensorFlow. When a model needs to move from a training notebook to a deployed API, a mobile app, a browser, or any environment that is not Python, SavedModel is the universal bridge. Mastering it ensures your trained models can reach users on any platform. The next topic covers TensorFlow Serving — the production server that exposes SavedModels as REST and gRPC APIs at scale.

Leave a Comment

Your email address will not be published. Required fields are marked *