Tensorflow
tf.NodeDef
machine learning
deep learning
Tensorflow tutorial

Tensorflow create tf.NodeDef and set attributes

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

NodeDef is TensorFlow's low-level protocol buffer for describing a graph node. Most application code never needs to build one manually, because normal TensorFlow ops generate the graph metadata for you. When you are doing graph transforms, serialization tooling, or debugging imported graphs, though, knowing how to create a NodeDef and set attributes is useful.

When NodeDef Is the Right Tool

Manual NodeDef creation is appropriate for advanced tasks such as:

  • building or editing a GraphDef
  • writing graph conversion tools
  • inspecting TensorFlow internals
  • generating nodes for test fixtures

For ordinary modeling code, prefer high-level APIs like tf.constant, tf.add, or Keras layers. They are easier to read and much harder to misconfigure.

Import the Protobuf Types

In modern TensorFlow, NodeDef and attribute messages live in TensorFlow's internal protobuf modules.

python
1import tensorflow as tf
2from tensorflow.core.framework import attr_value_pb2
3from tensorflow.core.framework import graph_pb2
4from tensorflow.core.framework import node_def_pb2
5from tensorflow.python.framework import tensor_util

You can build a node by filling in its name, op type, inputs, and attribute map.

Create a Const Node

A good first example is a constant node. A Const op typically needs at least:

  • 'name'
  • 'op'
  • 'dtype attribute'
  • 'value attribute'
python
1import tensorflow as tf
2from tensorflow.core.framework import attr_value_pb2
3from tensorflow.core.framework import node_def_pb2
4from tensorflow.python.framework import tensor_util
5
6node = node_def_pb2.NodeDef()
7node.name = "my_const"
8node.op = "Const"
9
10tensor_proto = tensor_util.make_tensor_proto([1, 2, 3], dtype=tf.int32)
11
12node.attr["dtype"].CopyFrom(
13    attr_value_pb2.AttrValue(type=tf.int32.as_datatype_enum)
14)
15node.attr["value"].CopyFrom(
16    attr_value_pb2.AttrValue(tensor=tensor_proto)
17)
18
19print(node)

The dtype attribute stores the TensorFlow datatype enum. The value attribute stores a serialized tensor payload.

Create an AddV2 Node with Inputs

Non-constant operations usually need input names and type attributes. Here is a minimal AddV2 node that adds two tensors.

python
1from tensorflow.core.framework import node_def_pb2, attr_value_pb2
2
3add_node = node_def_pb2.NodeDef()
4add_node.name = "sum_node"
5add_node.op = "AddV2"
6add_node.input.extend(["left", "right"])
7add_node.attr["T"].CopyFrom(
8    attr_value_pb2.AttrValue(type=tf.float32.as_datatype_enum)
9)
10
11print(add_node)

The input names refer to other nodes already present in the same graph definition.

Assemble a Complete GraphDef

To make this concrete, build a graph with two constants and one add node, then import it into TensorFlow.

python
1import tensorflow as tf
2from tensorflow.core.framework import attr_value_pb2
3from tensorflow.core.framework import graph_pb2
4from tensorflow.core.framework import node_def_pb2
5from tensorflow.python.framework import tensor_util
6
7
8def make_const(name, value, dtype):
9    node = node_def_pb2.NodeDef()
10    node.name = name
11    node.op = "Const"
12    node.attr["dtype"].CopyFrom(
13        attr_value_pb2.AttrValue(type=dtype.as_datatype_enum)
14    )
15    node.attr["value"].CopyFrom(
16        attr_value_pb2.AttrValue(
17            tensor=tensor_util.make_tensor_proto(value, dtype=dtype)
18        )
19    )
20    return node
21
22
23left = make_const("left", 3.0, tf.float32)
24right = make_const("right", 4.5, tf.float32)
25
26add_node = node_def_pb2.NodeDef()
27add_node.name = "sum_node"
28add_node.op = "AddV2"
29add_node.input.extend(["left", "right"])
30add_node.attr["T"].CopyFrom(
31    attr_value_pb2.AttrValue(type=tf.float32.as_datatype_enum)
32)
33
34graph_def = graph_pb2.GraphDef()
35graph_def.node.extend([left, right, add_node])
36
37graph = tf.Graph()
38with graph.as_default():
39    tf.compat.v1.import_graph_def(graph_def, name="")
40
41    with tf.compat.v1.Session(graph=graph) as sess:
42        result = sess.run(graph.get_tensor_by_name("sum_node:0"))
43        print(result)  # 7.5

This example is intentionally low-level. It demonstrates that the NodeDef attributes must match the selected op exactly.

Understanding Attribute Names

Attribute names depend on the operation. Examples:

  • 'Const uses dtype and value'
  • 'AddV2 uses T'
  • many reduction ops use booleans such as keep_dims

The safest way to learn the required attributes is to inspect the op definition or build a similar graph with high-level TensorFlow code and inspect its serialized GraphDef.

A Practical Debugging Technique

If you are unsure how to populate a node, first create the equivalent high-level op and inspect the generated node.

python
1import tensorflow as tf
2
3g = tf.Graph()
4with g.as_default():
5    a = tf.constant(1.0, name="a")
6    b = tf.constant(2.0, name="b")
7    c = tf.add(a, b, name="c")
8
9for node in g.as_graph_def().node:
10    print(node.name, node.op, list(node.attr.keys()))

This gives you a reference layout that is often easier than reading protobuf definitions directly.

Common Pitfalls

  • Using NodeDef for normal application code instead of higher-level TensorFlow ops.
  • Setting the wrong attribute name for an operation, such as dtype where the op expects T.
  • Forgetting to add input node names in dependency order within the same GraphDef.
  • Supplying a tensor value whose dtype does not match the declared type attribute.
  • Mixing eager-mode expectations with low-level graph-construction APIs.

Summary

  • 'NodeDef is a low-level protobuf used to describe TensorFlow graph nodes.'
  • Create a node by setting its name, op type, inputs, and correctly named attributes.
  • 'Const nodes usually need dtype and value, while many math ops use T.'
  • Build the equivalent high-level op first if you are unsure about required attributes.
  • Use NodeDef mainly for tooling, graph manipulation, and advanced debugging tasks.

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.