TensorFlow
Running TensorFlow frozen graphs directly via JavaCPP TF bindings
TensorFlow Direct Inference
The nd4j-tensorflow module runs TensorFlow frozen graphs natively using JavaCPP TF bindings. There is no conversion to a SameDiff graph; the TF runtime executes the graph directly. This is appropriate when you have a stable frozen graph and want low-overhead inference without the SameDiff import layer.
For models that need graph inspection or further training in Java, use SameDiff TF import instead.
When to Use TF Direct vs SameDiff Import
Pure inference, stable frozen graph
Yes
Yes
Graph inspection in Java
No
Yes
Further training in Java
No
Yes
Dependency on TF native libraries
Yes (JavaCPP)
No
Access TF-specific ops not in SameDiff
Yes
No
Maven Dependency
<dependency>
<groupId>org.nd4j</groupId>
<artifactId>nd4j-tensorflow</artifactId>
<version>${dl4j.version}</version>
</dependency>The module bundles TensorFlow native libraries via JavaCPP presets for Linux x86_64, Windows x86_64, and macOS.
Preparing the Model
TF direct inference requires a frozen graph (a protobuf where all Variable ops have been converted to constants). See TensorFlow Import — Preparing Your Model for Python export instructions.
Running Inference
Use TensorFlowRunner to load and execute a frozen graph:
GraphRunner Builder Options
GraphRunner is AutoCloseable:
Data Format Notes
TensorFlow defaults to NHWC (channels-last) data format for images: [batch, height, width, channels]. This differs from ND4J's default NCHW. Construct your input INDArray in NHWC order for TF models that were not explicitly configured for NCHW.
If your model uses data_format='channels_first' (NCHW), adjust accordingly:
Getting Node Names
To find placeholder and output node names in a frozen graph:
Complete Example
Troubleshooting
Native library load failure: the TF JavaCPP preset must match your platform. Verify that the artifact downloaded native libraries for your OS. On Linux, LD_LIBRARY_PATH may need to include the directory containing libtensorflow.so.
Node name not found: node names in TF frozen graphs are case-sensitive and include the full path (e.g., conv1/Relu not just Relu). Use the Python node listing snippet to find exact names.
Variable op in graph: GraphRunner requires a fully frozen graph. Variables that were not converted to constants cause runtime errors. Re-run the Python freezing step.
Last updated
Was this helpful?