- Implement message passing and a graph convolutional layer and compute a GCN update by hand
- Derive the recurrent and convolutional views of a discretized state-space model and compute both
- Explain how Mamba's input-dependent parameters make an SSM selective and why that requires a parallel scan
- Compare linear attention, SSMs and softmax attention in compute, memory and recall ability
- Analyse the KV-cache savings of hybrid attention/SSM models using documented examples
- Choose between transformers, GNNs, SSMs, hybrids, MoE and diffusion transformers for a given problem
Before this: Transformers: A Deep Dive, Recurrent Networks and Sequence Modelling
Why look beyond the transformer
Transformers dominate, but they make two assumptions that do not always fit. They treat input as a sequence (or a set) of tokens, while molecules, road networks, supply chains and social graphs are graphs with explicit connections. And their attention cost grows with the square of sequence length while the KV cache grows linearly, which makes very long contexts and high-concurrency serving expensive. This lesson covers the main architectural answers: graph neural networks for relational data, state-space models and linear attention for linear-time sequence modelling, the hybrid models that mix them with attention, mixture-of-experts as a way to scale parameters without scaling compute, and transformers used as diffusion denoisers. The goal is to know what each one buys you and when to reach for it.
Intuition: match the architecture to the shape of the data and the cost you can pay
A CNN assumes a grid, an RNN assumes a chain, and a transformer assumes every token may need to talk to every other token. A graph neural network assumes information flows along given edges — like gossip spreading only between friends. A state-space model is a return to the RNN's running summary, rebuilt so that it trains in parallel and chooses what to remember. A hybrid model is a pragmatic compromise: most layers keep a cheap fixed-size memory, and a few layers keep full attention for the moments when the model must look something up exactly.
Part 1: Graph neural networks
A graph has nodes with feature vectors , and edges, encoded in an adjacency matrix with if and are connected. Tasks are node-level (classify each account as fraud or not), edge-level (predict a missing link: will this user buy this item?) or graph-level (predict a molecule's toxicity).
Message passing
Almost every GNN fits the message-passing template (formalized by Gilmer et al., 2017). In layer , each node gathers messages from its neighbours , aggregates them with a permutation-invariant function, and updates its state:
is sum, mean or max (it must not depend on neighbour order, since graphs have none), and are small neural networks, and are optional edge features. After layers a node's representation depends on its -hop neighbourhood — the graph analogue of a receptive field. For graph-level tasks, a readout (sum or mean over all nodes) produces one vector per graph.
Graph convolutional network (GCN)
The GCN of Kipf and Welling (2016) is the simplest widely used instance. Add self-loops, , let be the diagonal degree matrix of , and set
stacks node states, is a learned weight matrix shared by all nodes (weight sharing again), and is a nonlinearity. The normalized matrix has entries for connected : each node averages itself and its neighbours, down-weighting high-degree hubs so they do not dominate.
Worked example. Path graph 1 — 2 — 3 with scalar features and . With self-loops the degrees are . So , , , , .
- Node 1:
- Node 2:
- Node 3:
Each node's new value blends its own feature with its neighbours'. Repeat this many times and all nodes converge toward similar values — over-smoothing, the reason most GNNs use only 2–4 layers.
import torch, torch.nn as nn
class GCNLayer(nn.Module):
def __init__(self, d_in, d_out):
super().__init__()
self.lin = nn.Linear(d_in, d_out, bias=False)
def forward(self, X, A): # X: (N, d_in); A: (N, N) 0/1
A_t = A + torch.eye(A.shape[0]) # self-loops
d_inv_sqrt = A_t.sum(1).pow(-0.5)
A_hat = d_inv_sqrt[:, None] * A_t * d_inv_sqrt[None, :] # D^-1/2 A D^-1/2
return A_hat @ self.lin(X)
A = torch.tensor([[0, 1, 0], [1, 0, 1], [0, 1, 0]], dtype=torch.float32)
X = torch.tensor([[1.0], [2.0], [3.0]])
layer = GCNLayer(1, 1)
with torch.no_grad():
layer.lin.weight.fill_(1.0)
print(layer(X, A).squeeze()) # tensor([1.3165, 2.2997, 2.3165])
class GCN(nn.Module): # 2-layer node classifier
def __init__(self, d_in, d_hidden, n_classes):
super().__init__()
self.l1, self.l2 = GCNLayer(d_in, d_hidden), GCNLayer(d_hidden, n_classes)
def forward(self, X, A):
return self.l2(torch.relu(self.l1(X, A)), A) # per-node logits
Dense adjacency is fine for teaching; real graphs are sparse, so libraries such as PyTorch Geometric and DGL use edge lists and scatter operations. Other important variants: GraphSAGE samples neighbours to scale to huge graphs; graph attention networks (GAT) learn per-edge weights with attention; graph transformers let all nodes attend to each other with structural position encodings. A transformer is in fact a GNN on a fully connected graph. GNNs are used for molecular property prediction, recommendation over user–item graphs, fraud rings in transaction graphs, traffic forecasting and chip design.
Part 2: State-space models
The continuous model and its two faces
A linear state-space model (SSM) maps an input signal to an output through a hidden state :
with , , . To apply it to tokens, discretize with a step size . The zero-order-hold rule gives
This is a linear RNN: constant work and memory per step at inference. Because are the same at every step (linear time-invariant), unrolling gives , which is a convolution with kernel . Training can therefore run as one long parallel convolution (via FFT), and inference as a recurrence.
Worked example. Scalar , , . Then and . Inputs :
- Recurrence: , , , .
- Convolution: , so . Same answer.
The state is a decaying memory: the impulse at step 1 fades by a factor of 0.6065 per step.
S4: making SSMs work for long sequences
Gu, Goel and Ré's S4 (2021) made deep SSMs practical. It initializes with a structure derived from the HiPPO theory of compressing history onto orthogonal polynomials, and parameterizes (normal plus low-rank) so the convolution kernel can be computed efficiently and stably. S4 reached state-of-the-art results on every task of the Long Range Arena benchmark, including the 16k-length Path-X task that earlier models had failed. But on language it still trailed transformers.
Mamba: selective state spaces
The weakness of time-invariant SSMs is that they treat every token the same; they cannot decide, based on content, to remember this name and ignore that filler word. Mamba (Gu and Dao, 2023) makes the SSM selective: the step size and the matrices and become functions of the current input (via small linear projections), while stays a learned diagonal matrix with negative entries:
(Mamba uses this simplified .) A large drives toward 0 — forget the past and focus on this token; a small keeps the state and nearly ignores the input. This is an input-dependent gate, much like an LSTM's forget gate, but on a linear recurrence.
The price is that the model is no longer time-invariant, so the convolution trick is gone. Mamba instead uses a hardware-aware parallel scan: the linear recurrence is associative, so it can be computed in parallel depth, and the kernel keeps the expanded state in fast SRAM rather than writing it to HBM — the same IO-awareness idea as FlashAttention. The paper reports training cost linear in sequence length, inference throughput about 5× that of transformers of similar size, and improving results on real data up to million-token sequences. Mamba-2 (Dao and Gu, 2024) restricted further to a scalar per head, showed a formal duality between this SSM and a form of masked linear attention, and used that duality for a faster, matrix-multiply-based training algorithm.
import torch, torch.nn as nn, torch.nn.functional as F
class NaiveSelectiveSSM(nn.Module):
"""Mamba-style selective SSM as a slow sequential loop, for understanding only."""
def __init__(self, d, N=16):
super().__init__()
self.A_log = nn.Parameter(torch.log(torch.arange(1, N + 1).float()).repeat(d, 1))
self.to_B, self.to_C, self.to_delta = nn.Linear(d, N), nn.Linear(d, N), nn.Linear(d, d)
def forward(self, x): # x: (B, T, d)
Bsz, T, d = x.shape
A = -torch.exp(self.A_log) # (d, N), negative = decaying
delta = F.softplus(self.to_delta(x)) # (B, T, d), input-dependent
Bt, Ct = self.to_B(x), self.to_C(x) # (B, T, N), input-dependent
h = x.new_zeros(Bsz, d, A.shape[1]) # fixed-size state
ys = []
for t in range(T):
dA = torch.exp(delta[:, t, :, None] * A) # (B, d, N)
dB = delta[:, t, :, None] * Bt[:, t, None, :] # (B, d, N)
h = dA * h + dB * x[:, t, :, None]
ys.append((h * Ct[:, t, None, :]).sum(-1)) # (B, d)
return torch.stack(ys, dim=1) # (B, T, d)
print(NaiveSelectiveSSM(d=8)(torch.randn(2, 20, 8)).shape) # torch.Size([2, 20, 8])
Each of the channels runs its own -dimensional state. A real Mamba block wraps this in an input projection, a short causal convolution, a gating branch and an output projection, and replaces the Python loop with the fused scan kernel.
Linear attention and the delta rule
A parallel line of work reaches the same place from the attention side. Replace with a kernel ; then causal attention becomes
— a recurrence with a fixed-size matrix state . Plain additive updates never forget and blur memories together, so newer variants add gates (decay of ) and the delta rule, which overwrites the value stored under a key instead of adding to it: in a common form, with a learned write strength . Gated DeltaNet (Yang et al., 2024) combines gating and the delta rule, and Kimi Delta Attention is a refinement of it.
The fundamental trade-off
A fixed-size state is what makes these models cheap, and it is also their limit: a state of a few megabytes cannot hold an exact copy of an arbitrarily long context. Pure recurrent models do well on language modelling perplexity but tend to struggle on tasks that require exact retrieval or copying of specific earlier content, where attention, with its growing cache, can simply look back. That observation drives the hybrid designs below.
Part 3: Hybrid architectures
A hybrid model interleaves a minority of full-attention layers with a majority of SSM or linear-attention layers. The attention layers provide precise lookup; the others provide cheap, constant-memory sequence mixing. As of November 2026, publicly documented examples include:
| Model (developer) | Released | Layer mix | Notes from the developer's documentation |
|---|---|---|---|
| Jamba (AI21 Labs) | Mar 2024 | 1 attention : 7 Mamba layers per block; MoE every other layer (16 experts, top-2) | 52B total / 12B active parameters; up to 256K context; 4 GB KV cache at 256K versus 32 GB for Mixtral |
| Nemotron-H (NVIDIA) | 2025 | About 8% of layers are self-attention; the rest split between Mamba-2 and MLP layers (8B: 4 attention, 24 Mamba-2, 24 MLP) | Reported up to 3× faster inference than similarly sized transformers |
| Granite 4.0-H (IBM) | Oct 2025 | Mamba-2 to transformer blocks at 9:1; Tiny and Small variants are MoE | IBM reports over 70% less RAM for long inputs and concurrent batches; Apache 2.0 |
| Qwen3-Next-80B-A3B (Alibaba Qwen) | Sep 2025 | 3 Gated DeltaNet : 1 gated attention (36 + 12 of 48 layers); MoE with 512 experts, 10 routed per token plus a shared expert | About 3B active of 80B; claims more than 10× throughput over Qwen3-32B beyond 32K context |
| Kimi Linear 48B-A3B (Moonshot AI) | Oct 2025 | About 3 Kimi Delta Attention : 1 MLA layer | Linear-attention-majority design with a small number of full-attention layers |
The memory effect is easy to compute with the KV-cache formula . A 32-layer transformer with 8 KV heads of dimension 128 in 16-bit stores bytes (128 KiB) per token, which is 32 GiB at 262,144 tokens. Keep attention in only 4 of 32 layers (a 1:7 ratio) and the cache becomes 16 KiB per token, or 4 GiB — an 8× reduction, matching Jamba's reported ratio — plus a fixed recurrent state for the other layers that does not grow with context. Faster decoding follows, because decode speed is largely bounded by bytes read per token (see tokens-per-second).
The trade-offs: fewer mature kernels and runtimes support SSM layers (IBM ships a pure-transformer Granite 4.0 Micro for platforms without hybrid support), quantization and serving tools lag behind, and the right ratio and placement of attention layers are still active research.
Part 4: Mixture-of-experts, recapped
Mixture-of-experts (MoE) is orthogonal to the attention-versus-recurrence question: it changes the MLP. A router scores expert MLPs; the token is sent to the top and the outputs are combined with normalized router weights:
Compute per token scales with , while total parameters scale with , so MoE buys capacity without proportional FLOPs. An auxiliary load-balancing loss keeps the router from sending everything to a few experts, and many designs add an always-on shared expert. Note from the table that hybrids and MoE combine naturally (Jamba, Granite 4.0-H Tiny/Small, Qwen3-Next). The memory catch: all experts must be resident, so memory follows total parameters while speed follows active parameters. Details are in mixture-of-experts.
Part 5: Diffusion transformers
Diffusion image generators were long built on U-Net convolutional denoisers. Peebles and Xie's Diffusion Transformer (DiT) (2022) showed that a plain transformer works as the denoiser: the image's latent representation (from a pretrained autoencoder) is cut into patches exactly as in a ViT, the timestep and class label condition each block through adaptive layer norm, and the output patches predict the noise. DiT's quality improved consistently with forward-pass compute (Gflops), from deeper or wider models or more tokens, and DiT-XL/2 reached an FID of 2.27 on class-conditional ImageNet 256×256, state of the art at the time. Transformer denoisers have since become common in large image and video generators; see diffusion-models.
Where each architecture wins
| Architecture | Wins when | Watch out for |
|---|---|---|
| Transformer | Most language, vision and multimodal tasks; exact in-context retrieval; best tooling | Quadratic prefill, KV cache growth with context and concurrency |
| GNN | Data is a graph with meaningful edges: molecules, transactions, networks | Over-smoothing, neighbour explosion on large graphs, dynamic graphs |
| SSM / linear attention | Very long sequences, streaming, constant-memory inference, audio and genomics | Weaker exact recall; less mature kernels and serving support |
| Hybrid | Long-context LLM serving where memory and throughput dominate cost | Attention-layer ratio and placement; runtime support |
| MoE | Need more capacity at fixed per-token compute | Total memory, routing imbalance, harder fine-tuning and serving |
| Diffusion transformer | Image, video and audio generation at scale | Many denoising steps; quadratic cost in patch count at high resolution |
Common pitfalls
- Treating graph data as a table: flattening relational data throws away the structure a GNN would exploit — and conversely, forcing a GNN onto data whose edges carry no signal.
- Deep GNNs: stacking many GCN layers over-smooths node features; prefer 2–4 layers plus residuals or jumping-knowledge connections.
- Leakage in graph splits: in link prediction, test edges must be removed from the message-passing graph.
- Judging SSMs by perplexity alone: evaluate retrieval and long-context tasks too, where fixed-state models may lag.
- Assuming a hybrid runs everywhere: check that your inference runtime, quantization format and hardware support its layer types before committing.
- Confusing MoE active and total parameters when sizing memory.
In practice
- Use PyTorch Geometric or DGL for GNNs, start with a 2-layer GCN or GraphSAGE baseline, and compare against a gradient-boosted model on hand-built graph features.
- For long-context or high-concurrency LLM serving, compare candidate models on cost per token at your real context lengths; hybrid and linear-attention models can win by large factors there while matching transformers at short context.
- Verify claims in model cards against your own evaluations, especially long-context recall.
- Keep transformers as the default when tooling, ecosystem and exact retrieval matter more than raw efficiency.
Key takeaways
- GNNs pass messages along edges with permutation-invariant aggregation; a GCN averages each node with its degree-normalized neighbours.
- A discretized linear SSM is both a linear RNN (cheap inference) and a long convolution (parallel training).
- Mamba makes the step size and the B and C matrices depend on the input, giving content-based forgetting at linear cost via a hardware-aware scan.
- Fixed-size recurrent state makes SSMs and linear attention cheap but limits exact recall, which is why hybrids keep a few attention layers.
- Documented hybrids such as Jamba, Nemotron-H, Granite 4.0-H and Qwen3-Next keep attention in roughly 8-25% of layers and cut KV-cache memory accordingly.
- MoE scales parameters without scaling per-token compute, and diffusion transformers apply the ViT recipe to denoising.
Terms in this lesson
- Message passing
- The GNN computation in which each node aggregates transformed messages from its neighbours and updates its own representation.
- Graph convolutional network (GCN)
- A GNN layer that multiplies node features by a learned matrix and averages them over each node's self-looped neighbourhood using symmetric degree normalization.
- Over-smoothing
- The tendency of node representations in deep GNNs to converge to similar values as repeated averaging spreads information across the graph.
- State-space model (SSM)
- A sequence model defined by a linear recurrence h_t = A-bar h_{t-1} + B-bar x_t with readout y_t = C h_t, obtained by discretizing a continuous linear system.
- Selective SSM
- An SSM whose discretization step and input and output matrices are computed from the current input, letting it choose what to keep or forget.
- Linear attention
- An attention variant that replaces the softmax with a kernel feature map so causal attention can be computed as a recurrence over a fixed-size state.
- Hybrid architecture
- A model that interleaves a small number of full-attention layers with a majority of SSM or linear-attention layers.
- Diffusion transformer (DiT)
- A diffusion model whose denoising network is a transformer operating on patches of a latent image rather than a convolutional U-Net.
Check your understanding
- 1.
In a GCN, what is the purpose of the symmetric normalization D^-1/2 (A + I) D^-1/2?
- 2.
In Mamba's selective SSM, which quantities are computed from the current input token?
- 3.
A pharmaceutical team wants to predict the solubility of small molecules from their atom-bond structure. Which architecture is the most natural first choice?
- 4.
A 32-layer transformer is converted into a hybrid that keeps attention in 4 layers and uses Mamba layers elsewhere, with the same KV-head configuration. By roughly what factor does the KV cache at a fixed context shrink?
- 5.
Why do most production hybrid models keep some full-attention layers rather than going fully recurrent?
Exercises
Work each problem before opening the solution.
- Exercise 1Core
A star graph has a centre node 1 connected to leaves 2, 3 and 4. Features are and with no nonlinearity. Apply two GCN propagation steps and , showing . What do you notice, and what does it suggest about depth?
Show solution
With self-loops the degrees are . Entries: , for leaves , , and 0 between different leaves.
Step 1: centre ; each leaf . So .
Step 2: centre ; each leaf . So .
The signal that started only at the centre has spread to all nodes, and the leaves are identical (they are structurally symmetric). With more steps the values settle into a fixed pattern proportional to (here centre:leaf ; the ratio goes and oscillates toward 1.41), a pattern that depends only on the graph's degrees and no longer on where the signal started. That loss of node-specific information is over-smoothing. That is why GCNs are usually 2-4 layers deep and use residual connections when deeper.
- Exercise 2Core
A scalar SSM has , , . (a) Compute and with zero-order hold. (b) For inputs compute by recurrence, and verify with the convolution kernel. (c) In a selective SSM, what happens at a step where the model outputs a very large ?
Show solution
(a) . . .
(b) Recurrence with :
- , so
- , so
Kernel . . Matches.
(c) With , a very large makes , wiping the previous state, while the input term becomes large: the model resets and stores the current token. A tiny does the opposite, keeping the state and nearly ignoring the token. This is content-dependent forgetting.
- Exercise 3Challenge
Compare memory at a 131,072-token context for two 48-layer models with 8 KV heads of dimension 128 in 16-bit: (A) all layers are full attention; (B) a 3:1 hybrid with 12 full-attention layers and 36 linear-attention layers, each linear layer keeping 16 heads of 128 x 128 state in 16-bit. Compute the per-token KV cache, total context memory for one sequence, and the ratio. Then explain why per-token decode is still not constant-time for model B.
Show solution
Model A: per token bytes KiB. At 131,072 tokens: GiB.
Model B: attention layers: bytes KiB per token, so 6 GiB at 131,072 tokens. Linear-attention state: bytes KiB per layer, times 36 layers MiB, independent of context. Total about GiB.
Ratio: about less memory per sequence, which also means roughly 4x more concurrent long sequences in the same memory.
Decode for model B is still per token because its 12 attention layers must read the whole cached context for every new token; only the 36 linear layers are constant-time. The attention share is 4x smaller, so the context-dependent part of decode cost drops about 4x, but it still grows with context.
- Exercise 4Challenge
Show in code that causal linear attention with feature map can be computed either in a parallel form (masked matrix products, as in training) or as a recurrence with a constant-size state (as in inference), and that the two give identical outputs.
Show solution
import torch, torch.nn.functional as F torch.manual_seed(0) T, dk, dv = 6, 4, 3 phi = lambda z: F.elu(z) + 1 # strictly positive features Q, K, V = torch.randn(T, dk), torch.randn(T, dk), torch.randn(T, dv) q, k = phi(Q), phi(K) # parallel form: causal mask on the (unnormalized) kernel scores scores = (q @ k.T) * torch.tril(torch.ones(T, T)) par = (scores @ V) / scores.sum(-1, keepdim=True) # recurrent form: state S (dk x dv) and normalizer z (dk) S, z, rec = torch.zeros(dk, dv), torch.zeros(dk), [] for t in range(T): S = S + torch.outer(k[t], V[t]) z = z + k[t] rec.append((q[t] @ S) / (q[t] @ z)) rec = torch.stack(rec) print(torch.allclose(par, rec, atol=1e-5)) # TrueBoth compute . The parallel form costs but uses big matrix multiplies (good for training on GPUs, and chunked variants reduce it further); the recurrent form costs per token with a state (good for generation). Softmax attention has no such factorization because does not split into a product of separate functions of and with a finite feature map.
Further reading
- paperKipf & Welling, Semi-Supervised Classification with Graph Convolutional Networks (2016)
- paperGu, Goel & Re, Efficiently Modeling Long Sequences with Structured State Spaces (2021)
- paperGu & Dao, Mamba: Linear-Time Sequence Modeling with Selective State Spaces (2023)
- paperLieber et al., Jamba: A Hybrid Transformer-Mamba Language Model (2024)
- paperNVIDIA, Nemotron-H: A Family of Accurate and Efficient Hybrid Mamba-Transformer Models (2025)
- paperPeebles & Xie, Scalable Diffusion Models with Transformers (2022)
Go further
Sources
- Lieber et al. (2024), Jamba (arXiv HTML)
- NVIDIA (2025), Nemotron-H (arXiv HTML)
- IBM, Granite 4.0: hyper-efficient, high performance hybrid models for enterprise (2 Oct 2025)
- Hugging Face Transformers documentation: Qwen3-Next
- Sebastian Raschka, LLM Architecture Gallery: hybrid attention
- Gu & Dao (2023), Mamba
- Gu, Goel & Re (2021), S4
- Peebles & Xie (2022), DiT
Fact-checked and last reviewed 2026-11-05