> 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-beta7/nd4j/overview-2/serialization.md).

# Serialization

SameDiff graphs — including their structure, variables, constants, and trained parameters — can be saved to and loaded from files using the FlatBuffers binary format. This enables model deployment, checkpointing during training, and sharing trained models.

## Saving a SameDiff Graph

### save()

Save the complete graph including all variables, constants, and parameter values:

```java
import org.nd4j.autodiff.samediff.SameDiff;
import java.io.File;

// Save with updater state (for resuming training)
sd.save(new File("model.fb"), true);

// Save without updater state (smaller file, for inference only)
sd.save(new File("model.fb"), false);
```

The second argument controls whether to include the updater state (momentum buffers, adaptive learning rate accumulators, etc.). Include it if you plan to resume training; omit it for inference-only deployment.

### asFlatGraph()

Convert the graph to a FlatBuffers byte buffer in memory (useful for embedding in other formats or sending over the network):

```java
import java.nio.ByteBuffer;

ByteBuffer buffer = sd.asFlatGraph(true);  // true = include updater state
```

### asFlatPrint()

Get a human-readable string representation of the graph (for debugging):

```java
String graphString = sd.asFlatPrint();
System.out.println(graphString);
```

This prints the graph structure, variable names, shapes, and operation types.

## Loading a SameDiff Graph

### load()

Load a previously saved graph:

```java
// Load with updater state (for resuming training)
SameDiff sd = SameDiff.load(new File("model.fb"), true);

// Load without updater state (for inference)
SameDiff sd = SameDiff.load(new File("model.fb"), false);
```

### fromFlatGraph()

Load from a FlatBuffers byte buffer:

```java
import org.nd4j.autodiff.samediff.SameDiff;
import java.nio.ByteBuffer;

SameDiff sd = SameDiff.fromFlatGraph(byteBuffer);
```

## What Gets Saved

| Component                          | Saved        | Notes                                                      |
| ---------------------------------- | ------------ | ---------------------------------------------------------- |
| Graph structure (ops, connections) | Always       | The computation graph topology                             |
| VARIABLE values (weights, biases)  | Always       | Trainable parameters                                       |
| CONSTANT values                    | Always       | Non-trainable stored values                                |
| PLACEHOLDER definitions            | Always       | Shape and type info (not values)                           |
| ARRAY definitions                  | Always       | Shape and type info (not values — computed at runtime)     |
| Updater state                      | Optional     | Momentum/adaptive rate buffers. Only if `saveUpdater=true` |
| TrainingConfig                     | With updater | Optimizer settings                                         |

## Training Checkpoints

Save periodic checkpoints during training for recovery:

```java
for (int epoch = 0; epoch < numEpochs; epoch++) {
    sd.fit(trainIter, 1);
    trainIter.reset();

    // Save checkpoint every 5 epochs (with updater state)
    if (epoch % 5 == 0) {
        sd.save(new File("checkpoint_epoch_" + epoch + ".fb"), true);
    }
}

// Save final model (without updater state — smaller)
sd.save(new File("final_model.fb"), false);
```

Resume training from a checkpoint:

```java
SameDiff sd = SameDiff.load(new File("checkpoint_epoch_10.fb"), true);

// Re-set training config if needed
sd.setTrainingConfig(TrainingConfig.builder()
    .updater(new Adam(1e-4))    // can change learning rate
    .dataSetFeatureMapping("input")
    .dataSetLabelMapping("label")
    .build());

// Continue training
sd.fit(trainIter, remainingEpochs);
```

## Interop with Model Import

SameDiff is also the target format for model import from other frameworks. When you import a TensorFlow or ONNX model, the result is a `SameDiff` graph:

```java
// TensorFlow import
import org.nd4j.imports.graphmapper.tf.TFGraphMapper;
SameDiff sd = TFGraphMapper.importGraph(new File("frozen_model.pb"));

// ONNX import
import org.nd4j.imports.graphmapper.onnx.OnnxGraphMapper;
SameDiff sd = OnnxGraphMapper.importGraph(new File("model.onnx"));

// Run inference on the imported model
Map<String, INDArray> placeholders = new HashMap<>();
placeholders.put("input:0", inputData);
INDArray output = sd.outputSingle(placeholders, "output:0");

// Save as FlatBuffers for faster subsequent loading
sd.save(new File("converted_model.fb"), false);
```

This workflow (import once, save as FlatBuffers, load FlatBuffers for serving) avoids repeated parsing of the original model format.

## File Format Details

SameDiff uses [FlatBuffers](https://google.github.io/flatbuffers/) as its serialization format:

* **Binary format**: Compact, fast to serialize/deserialize
* **No schema evolution issues**: Forward and backward compatible
* **Zero-copy reads**: FlatBuffers can be read directly from the buffer without unpacking
* **Cross-platform**: Same file works on any OS/architecture

Typical file sizes depend on model complexity:

* Simple MLP (784→256→10): \~1-2 MB
* ResNet-18: \~45 MB
* Large transformer: 100+ MB

## Best Practices

1. **Save without updater state for deployment** — reduces file size significantly (updater state can be 2-3x the model parameters for Adam)
2. **Save with updater state for checkpoints** — allows seamless training resumption
3. **Convert imported models to FlatBuffers** — much faster to load than parsing TF/ONNX format each time
4. **Version your saved models** — include epoch/date in filenames for traceability
5. **Verify after loading** — run a sample inference to confirm the loaded model produces expected results

```java
// Quick verification after loading
SameDiff sd = SameDiff.load(new File("model.fb"), false);
INDArray testInput = Nd4j.rand(DataType.FLOAT, 1, inputSize);
Map<String, INDArray> ph = Collections.singletonMap("input", testInput);
INDArray output = sd.outputSingle(ph, "predictions");
System.out.println("Output shape: " + Arrays.toString(output.shape()));
System.out.println("Output: " + output);
```


---

# 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-beta7/nd4j/overview-2/serialization.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.
