frozen model
input nodes
output nodes
deep learning
machine learning

How to find the Input and Output Nodes of a Frozen Model

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

A frozen model is usually a TensorFlow graph definition, often stored as a .pb file, where variables have been turned into constants for inference. To run inference or convert the model to another format, you need to know which nodes feed data into the graph and which nodes represent the final outputs you care about.

The awkward part is that a frozen graph can contain many operations, including preprocessing, intermediate tensors, and control nodes. So "find the inputs and outputs" usually means inspecting the graph and identifying placeholders on the front edge and terminal prediction tensors on the back edge.

Load the Frozen Graph

In legacy TensorFlow workflows, a frozen graph is often inspected through tf.compat.v1:

python
1import tensorflow as tf
2
3
4def load_graph(pb_path):
5    graph = tf.Graph()
6    with graph.as_default():
7        graph_def = tf.compat.v1.GraphDef()
8        with tf.io.gfile.GFile(pb_path, "rb") as f:
9            graph_def.ParseFromString(f.read())
10        tf.import_graph_def(graph_def, name="")
11    return graph
12
13
14graph = load_graph("frozen_model.pb")

Using name="" avoids adding a prefix such as import/, which makes node names easier to read.

Find Likely Input Nodes

For many frozen models, input nodes are operations of type Placeholder:

python
for op in graph.get_operations():
    if op.type == "Placeholder":
        print("INPUT:", op.name, op.outputs[0].shape)

This is often enough for simple inference graphs. A placeholder is a strong hint that external data is expected to be fed there.

Be aware that some graphs have multiple placeholders, such as:

  • the main input tensor,
  • a dropout keep-prob placeholder in older models,
  • a boolean training flag,
  • sequence-length tensors or auxiliary inputs.

So not every placeholder is necessarily a user-facing model input.

Find Likely Output Nodes

A common heuristic is to look for ops whose outputs are not consumed by later ops:

python
1consumer_map = {}
2for op in graph.get_operations():
3    for tensor in op.inputs:
4        consumer_map.setdefault(tensor.name, 0)
5        consumer_map[tensor.name] += 1
6
7for op in graph.get_operations():
8    for out in op.outputs:
9        if out.name not in consumer_map:
10            print("POSSIBLE OUTPUT:", out.name, out.shape)

This lists terminal tensors. It is a useful starting point, though some terminal nodes may be irrelevant housekeeping outputs rather than the final prediction you want.

Use Graph Semantics, Not Just Heuristics

Placeholders and terminal tensors are heuristics, not perfect truth. You still need to interpret the model:

  • a node named input_ids or images is often a true input,
  • a node named Softmax, Identity, ArgMax, or logits is often a likely output,
  • dropout or training placeholders may not be needed for inference,
  • some models expose an Identity op just to give the final tensor a stable export name.

That is why inspecting node names is often as important as inspecting node types.

A Practical Inspection Script

Here is a compact script that prints both placeholders and terminal tensors:

python
1graph = load_graph("frozen_model.pb")
2
3print("=== Inputs ===")
4for op in graph.get_operations():
5    if op.type == "Placeholder":
6        print(op.name, op.outputs[0].shape)
7
8print("=== Candidate Outputs ===")
9consumed = set()
10for op in graph.get_operations():
11    for tensor in op.inputs:
12        consumed.add(tensor.name)
13
14for op in graph.get_operations():
15    for tensor in op.outputs:
16        if tensor.name not in consumed:
17            print(tensor.name, tensor.shape)

This gives you a manageable list to compare against documentation, training code, or model-export scripts.

Common Pitfalls

  • Assuming every placeholder is a real user input rather than a training-only control tensor.
  • Assuming every terminal tensor is the desired prediction output.
  • Forgetting that imported graphs may add name prefixes if imported with a non-empty scope.
  • Treating all .pb files the same without knowing whether they are frozen graphs, SavedModel assets, or something else.
  • Skipping node-name inspection and relying only on op type.

Summary

  • Frozen models are usually inspected by loading the graph and listing operations.
  • 'Placeholder ops are the first place to look for inputs.'
  • Tensors with no consumers are good candidates for outputs.
  • Node names such as logits, Softmax, or Identity often help confirm the real inference outputs.
  • Heuristics get you close, but final confirmation should come from model context or export documentation.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.