Custom Graph Blocks
Drop below the Sequential convenience layer and compose differentiable math, neural, structural, and sequence operations into reusable trainable blocks.
The auto-differentiating graph engine
Sequential layers are built on a lower-level graph runtime. Each node records a forward operation and enough context for the backward pass. When a custom block is inserted into a compiled model, its trainable parameters participate in the same loss, optimizer, clipping, and training workflow as built-in layers.
GraphBlock workflow
nl.GraphBlock myBlock = nl.graphBlock("custom")
// Define inputs, trainable parameters, constants, and operations.
// Select the final graph node with .output().
model := model
.input(array.from(8), "features")
.block(myBlock)
.dense(1, nl.ActivationKind.linear, "output")
.compile(cfg)- Declare an input node and its feature shape.
- Create trainable parameters or fixed constants.
- Wire operations in dependency order.
- Mark one node as the block output.
- Insert the block with
.block().
Operation families
| Family | Operations |
|---|---|
| Math | Matrix multiplication, transpose, add, subtract, multiply, divide, and scale. |
| Neural | Activations, softmax, layer normalization, and dropout. |
| Structure | Causal masks, row/column slicing, concatenation, and reduction. |
| Sequence | Global pooling, attention score/apply, Conv1D, LSTM scan, and GRU scan. |
Composition with Sequential
A block behaves like another layer in the fluent chain. This is how NeuraLib_Models adds architecture families without duplicating tensor, optimizer, dataset, or training infrastructure.
Design rules
- Validate early: fail before graph execution when feature counts or packed row layouts are incompatible.
- Keep dependencies topological: Pine declarations and graph nodes must exist before they are referenced.
- Stay compact: every added operation consumes compiled tokens and runtime budget.
- Probe forward shape first: build and predict before adding a training loop.
- Test gradients separately: a valid forward pass does not guarantee the intended backward behavior.
When to use a custom block
Use GraphBlock when the operation is not expressible as a short Sequential chain, when parameters must be shared inside one topology, or when you are building a reusable architecture extension. Prefer core layers for ordinary dense models.