TensorFlow
SavedModel
TensorFlow Serving
Cloud ML Engine
Graph Conversion

Convert a graph proto pb/pbtxt to a SavedModel for use in TensorFlow Serving or Cloud ML Engine

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Older TensorFlow pipelines often produce frozen graph files in pb or pbtxt format, while modern deployment stacks expect SavedModel format. Converting correctly requires importing the graph, defining a concrete signature, and exporting with named inputs and outputs. Most deployment failures come from wrong tensor names, not from export code itself.

Why SavedModel Is Required

TensorFlow Serving and managed prediction services operate around SavedModel directories with signature definitions. A raw graph file lacks standardized serving signatures and asset structure.

A minimal SavedModel export gives you:

  • versioned model folder
  • explicit signature names
  • stable input and output bindings

Load a Frozen Graph in TensorFlow 2

Use compatibility APIs to parse GraphDef and wrap imported tensors.

python
1import tensorflow as tf
2
3
4def load_graph_def(pb_path):
5    graph_def = tf.compat.v1.GraphDef()
6    with tf.io.gfile.GFile(pb_path, "rb") as f:
7        graph_def.ParseFromString(f.read())
8    return graph_def
9
10
11def import_graph(graph_def):
12    wrapped = tf.compat.v1.wrap_function(
13        lambda: tf.compat.v1.import_graph_def(graph_def, name=""),
14        []
15    )
16    return wrapped

The empty name preserves original tensor naming from the graph.

Identify Correct Input and Output Tensor Names

Before export, inspect operations to locate serving tensors.

python
1def list_ops(graph):
2    for op in graph.get_operations()[:30]:
3        print(op.name)
4
5
6graph_def = load_graph_def("model.pb")
7wrapped = import_graph(graph_def)
8list_ops(wrapped.graph)

Use this output to choose exact tensor names such as input:0 and probabilities:0.

Build a Concrete Function Signature

Create a callable that maps a structured argument to output tensors.

python
1graph_def = load_graph_def("model.pb")
2wrapped = import_graph(graph_def)
3
4input_tensor = wrapped.graph.get_tensor_by_name("input:0")
5output_tensor = wrapped.graph.get_tensor_by_name("probabilities:0")
6
7infer = wrapped.prune(feeds=input_tensor, fetches=output_tensor)
8
9@tf.function(input_signature=[tf.TensorSpec(shape=[None, 224, 224, 3], dtype=tf.float32, name="input")])
10def serving_fn(x):
11    y = infer(x)
12    return {"scores": y}

The signature shape and dtype must match model expectations.

Export to SavedModel

Write the model with a named serving signature.

python
1export_dir = "saved_model/1"
2tf.saved_model.save(
3    obj=tf.Module(),
4    export_dir=export_dir,
5    signatures={"serving_default": serving_fn}
6)

For TensorFlow Serving, versioned folder naming like 1 is standard.

Validate Export Before Deployment

Use saved_model_cli to verify signature fields.

bash
saved_model_cli show --dir saved_model/1 --tag_set serve --signature_def serving_default

Then run a local inference smoke test with TensorFlow to confirm tensor shapes and outputs.

python
loaded = tf.saved_model.load("saved_model/1")
pred = loaded.signatures["serving_default"](input=tf.random.uniform([1, 224, 224, 3]))
print(pred["scores"].shape)

Early validation avoids deployment loops in serving infrastructure.

pbtxt Variant Notes

For pbtxt, parse text format first and convert to GraphDef.

python
1from google.protobuf import text_format
2
3
4def load_pbtxt(path):
5    graph_def = tf.compat.v1.GraphDef()
6    with tf.io.gfile.GFile(path, "r") as f:
7        text_format.Merge(f.read(), graph_def)
8    return graph_def

The rest of the export workflow stays the same.

Versioning and Backward Compatibility

During migration, keep old and new exports available at the same time so clients can be switched gradually. Store conversion scripts in version control and pin TensorFlow versions used for export. Small runtime differences between versions can alter signature behavior or tensor naming conventions, so reproducible export environments are important for stable production rollouts.

Document tensor names in deployment runbooks so operations teams can quickly verify signature health after releases.

Keep conversion checks in continuous integration.

Pin exporter dependencies so the same graph conversion command produces reproducible artifacts across developer machines and release environments.

Common Pitfalls

  • Guessing input and output tensor names instead of inspecting graph operations.
  • Exporting without explicit signature definitions, leading to unusable serving endpoints.
  • Using mismatched input shape or dtype between signature and frozen graph expectation.
  • Forgetting versioned folder layout required by TensorFlow Serving conventions.
  • Skipping saved_model_cli verification and discovering signature issues only after deployment.

Summary

  • Convert pb and pbtxt graphs by importing GraphDef and exporting a SavedModel signature.
  • Correct tensor naming is the most critical part of successful conversion.
  • Define explicit TensorSpec input signatures for serving stability.
  • Validate with saved_model_cli and local smoke tests before production rollout.
  • Use versioned export directories for serving compatibility.

Course illustration
Course illustration

All Rights Reserved.