> For the complete documentation index, see [llms.txt](https://deeplearning4j.konduit.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://deeplearning4j.konduit.ai/en-1.0.0-rewrite/model-import/overview-2/tensorflow.md).

# TensorFlow Import

### TensorFlow Import

The `nd4j-samediff-import-tensorflow` module imports TensorFlow frozen graphs (`.pb` protobuf files) and TensorFlow SavedModels into SameDiff. After import, the model lives as a native SameDiff graph.

***

### Maven Dependency

```xml
<dependency>
    <groupId>org.nd4j</groupId>
    <artifactId>nd4j-samediff-import-tensorflow</artifactId>
    <version>${dl4j.version}</version>
</dependency>
```

***

### Preparing Your TensorFlow Model

#### Exporting a Frozen Graph from TF 1.x

```python
import tensorflow as tf
from tensorflow.python.framework.graph_util import convert_variables_to_constants

# Assuming you have a trained session
with tf.Session() as sess:
    # ... restore or train your model ...

    # Freeze: convert variables to constants
    frozen_graph_def = convert_variables_to_constants(
        sess,
        sess.graph_def,
        output_node_names=['output/Softmax']  # your output node name(s)
    )

    # Write to disk
    with tf.io.gfile.GFile('frozen_model.pb', 'wb') as f:
        f.write(frozen_graph_def.SerializeToString())
```

#### Exporting a Frozen Graph from TF 2.x

```python
import tensorflow as tf

# Load a saved model or define your model
model = tf.saved_model.load('my_saved_model')

# Convert to concrete function
concrete_func = model.signatures['serving_default']

# Use tf2onnx or tf.lite.TFLiteConverter to export, OR
# use tf.compat.v1.graph_util to freeze

# Alternatively, save as SavedModel directory for direct import
model.save('my_saved_model_dir')
```

#### Getting Node Names

To identify placeholder (input) and output node names in a frozen graph:

```python
import tensorflow as tf

graph_def = tf.compat.v1.GraphDef()
with open('frozen_model.pb', 'rb') as f:
    graph_def.ParseFromString(f.read())

for node in graph_def.node:
    print(node.op, node.name)
```

***

### Importing a Frozen Graph

Use `TFGraphMapper` to import a TF frozen protobuf file:

```java
import org.nd4j.autodiff.samediff.SameDiff;
import org.nd4j.imports.graphmapper.tf.TFGraphMapper;

import java.io.File;

// Import a frozen graph
File frozenGraph = new File("frozen_model.pb");
SameDiff sd = TFGraphMapper.importGraph(frozenGraph);
```

You can also import from an `InputStream`:

```java
import java.io.FileInputStream;
import java.io.InputStream;

try (InputStream is = new FileInputStream("frozen_model.pb")) {
    SameDiff sd = TFGraphMapper.importGraph(is);
}
```

***

### Placeholder Mapping

TF frozen graphs have placeholder nodes for inputs. After import, you must provide values for each placeholder at inference time. Use `sd.output()` with a map from placeholder name to `INDArray`:

```java
import org.nd4j.linalg.api.ndarray.INDArray;
import org.nd4j.linalg.factory.Nd4j;

import java.util.HashMap;
import java.util.Map;

// Create input matching the placeholder's expected shape
INDArray inputData = Nd4j.rand(1, 224, 224, 3);  // NHWC for an image model

Map<String, INDArray> placeholders = new HashMap<>();
placeholders.put("input_1", inputData);  // use your actual placeholder name

// Run inference; specify which output nodes to evaluate
Map<String, INDArray> result = sd.output(placeholders, "output/Softmax");

INDArray predictions = result.get("output/Softmax");
System.out.println("Predictions shape: " + java.util.Arrays.toString(predictions.shape()));
```

***

### Multiple Inputs and Outputs

For models with multiple inputs:

```java
Map<String, INDArray> inputs = new HashMap<>();
inputs.put("input_text",   Nd4j.create(new float[]{1, 5, 3, 0, 0}, new int[]{1, 5}));
inputs.put("input_length", Nd4j.create(new float[]{3}, new int[]{1}));

Map<String, INDArray> results = sd.output(inputs, "output_logits", "output_probs");
INDArray logits = results.get("output_logits");
INDArray probs  = results.get("output_probs");
```

***

### Inspecting the Imported Graph

After import, you can inspect the graph structure:

```java
// Print summary of all variables and ops
System.out.println(sd.summary());

// List all placeholder (input) variable names
for (SDVariable v : sd.variables()) {
    if (v.isPlaceHolder()) {
        System.out.println("Placeholder: " + v.name() + " shape: " + v.getShape());
    }
}

// List op names
for (String opName : sd.ops().keySet()) {
    System.out.println("Op: " + opName);
}
```

***

### Supported TF Ops

The following categories of TensorFlow ops are mapped:

**Arithmetic and math:**

* Add, AddV2, Sub, Mul, Div, FloorDiv, FloorMod, Pow, Exp, Log, Sqrt, Square, Abs, Neg, Sign, Ceil, Floor, Round
* MatMul, BatchMatMul, BatchMatMulV2
* Minimum, Maximum, BiasAdd

**Neural network:**

* Conv2D, Conv2DBackpropInput, DepthwiseConv2dNative, Conv3D
* Relu, Relu6, Elu, Selu, LeakyRelu, Sigmoid, Tanh, Softmax, LogSoftmax
* MaxPool, AvgPool, MaxPool3D, AvgPool3D, MaxPoolV2
* FusedBatchNorm, FusedBatchNormV2, FusedBatchNormV3

**Shape and indexing:**

* Reshape, Transpose, Concat, ConcatV2, Stack, Unstack, Pack, Unpack
* Split, SplitV, Slice, StridedSlice, GatherV2, GatherNd, ScatterNd
* Squeeze, ExpandDims, Tile, Pad, PadV2, MirrorPad

**Reduction:**

* Sum (ReduceSum), Mean (ReduceMean), Max (ReduceMax), Min (ReduceMin)
* ReduceAll, ReduceAny, ReduceProd

**Type and cast:**

* Cast, Identity, Snapshot

**Control flow (TF 1.x):**

* Switch, Merge, Enter, Exit, NextIteration

**Recurrent:**

* LSTMBlockCell, BlockLSTM, GRUBlockCell

**Image:**

* ResizeBilinear, ResizeNearestNeighbor, CropAndResize, DecodeJpeg (decode only)

**Lookup and embedding:**

* ResourceGather, GatherV2

***

### Complete Example: MobileNet Inference

```python
# Python: export a MobileNet frozen graph
import tensorflow as tf
import numpy as np

# Load MobileNet from Keras (requires TF 1.x-compatible freeze)
from keras.applications import MobileNet
from keras.backend import get_session
from tensorflow.python.framework.graph_util import convert_variables_to_constants

model = MobileNet(weights='imagenet')
sess = get_session()

frozen = convert_variables_to_constants(
    sess,
    sess.graph_def,
    output_node_names=['act_softmax/Softmax']
)
with open('mobilenet_frozen.pb', 'wb') as f:
    f.write(frozen.SerializeToString())
```

```java
// Java: load and run inference
import org.nd4j.autodiff.samediff.SameDiff;
import org.nd4j.imports.graphmapper.tf.TFGraphMapper;
import org.nd4j.linalg.api.ndarray.INDArray;
import org.nd4j.linalg.factory.Nd4j;

import java.io.File;
import java.util.*;

public class MobileNetInference {
    public static void main(String[] args) throws Exception {
        SameDiff sd = TFGraphMapper.importGraph(new File("mobilenet_frozen.pb"));

        // MobileNet expects [batch, height, width, channels] in [0, 1] range
        INDArray image = Nd4j.rand(1, 224, 224, 3);

        Map<String, INDArray> inputs = new HashMap<>();
        inputs.put("input_1", image);

        Map<String, INDArray> results = sd.output(inputs, "act_softmax/Softmax");
        INDArray predictions = results.get("act_softmax/Softmax");

        // Find top-1 class
        int topClass = predictions.argMax(1).getInt(0);
        System.out.println("Top class index: " + topClass);
    }
}
```

***

### Troubleshooting

**Op not found**: a TF op in the frozen graph has no registered SameDiff mapper. Check the op name in the error message, verify the op list above, and open a GitHub issue if it should be supported.

**Placeholder name unknown**: run the Python snippet above to print all node names before import. Use the exact string that appears after the `Placeholder` op type.

**Shape mismatch at inference**: TF models trained with NHWC data format (TensorFlow default) expect inputs as `[batch, height, width, channels]`. Construct your `INDArray` accordingly.

**Variables not frozen**: if the frozen graph still contains `Variable` ops, the freeze step was incomplete. Ensure `convert_variables_to_constants` ran successfully and all variable names were captured.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://deeplearning4j.konduit.ai/en-1.0.0-rewrite/model-import/overview-2/tensorflow.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
