Paper · 2022-08-09 · cs.LG
Simplified State Space Layers for Sequence Modeling
S5 replaces S4's bank of single-input, single-output state space models with one multi-input, multi-output diagonal SSM. A parallel scan runs it in the time domain at S4's cost, and HiPPO-N initialisation keeps S4-level accuracy. Author-reported: 87.46% LRA average, 98.58% on Path-X, 94.53% on 8 kHz Speech Commands.
State-space model (SSM)Recurrent neural network (RNN)Parallel scan (prefix scan)sequence-modelingstate-space-modelsparallel-scan
arXivPDFCodeMarkdown12 min read
AI-compiled by claude-haiku-5-5 on 2026-10-19, not yet reviewed by a human. Every claim cites its source; check it when a detail matters.
In plain words
Many sequence tasks, such as reading a long document or listening to audio, need a model to connect things that are thousands of steps apart. The earlier S4 layer handled this well, but it did so with many small, separate memory units and a fairly involved calculation that turned them into a convolution.
S5 keeps the same kind of memory, a linear state space model, but uses one shared memory block in which all the inputs and outputs are mixed together. Because this block is simple and diagonal, its step-by-step updates can be computed in parallel with a standard "scan" trick, the same kind of operation used for prefix sums. The result runs in the time domain, works for sequences that are sampled at irregular times, and is about as fast as S4.
The authors also show that the starting values for the memory match those of S4 closely enough to keep its accuracy on long-range benchmarks. The numbers reported are the authors' own.
TL;DR
S5 is a state space layer whose state transition is diagonal. It runs as a parallel linear recurrence over time, with per-mode learnable timescales. It is initialised from a diagonalised HiPPO-N matrix and matches S4's asymptotic cost when the state size is on the order of the feature size §3.4. The paper reports state-of-the-art results on Long Range Arena (LRA) and Speech Commands at 8 kHz, and near-S4 results on the rest. Treat the numbers as author-reported.
Problem
S4 applies a bank of independent single-input, single-output state space models (SSMs), one per feature channel. Efficient training uses a frequency-domain convolution kernel, which needs a non-trivial computation and assumes a time-invariant system with regularly spaced observations §2.3 §3.3. The HiPPO-LegS matrix that S4 uses for initialisation cannot be diagonalised stably, which blocks a direct parallel-scan version §2.3 §4.2. Efficient transformers still perform poorly on very long-range tasks §1.
Method
The S5 layer has one MIMO SSM with latent size P and input and output size H §3.1. The continuous system is diagonalised, A = V Λ V⁻¹, and rewritten with reparameterised input and output matrices B̃ = V⁻¹B and C̃ = CV eq. 4 eq. 5. Each diagonal mode gets a learnable timescale Δ ∈ ℝ^P, and the system is discretised by zero-order hold §3.2 eq. 6. A feedthrough matrix D is restricted to be diagonal §3.2.
Steps for one layer, applied to a sequence u₁:L of shape (L, H):
- Discretise each diagonal mode with its own timescale §3.2 eq. 6.
- Run the linear recurrence over time with a parallel scan on the pairs (Λ̄, B̄uₖ). The scan operator is associative §2.2 app. H.
- Read out the real part of C̃xₖ and add the feedthrough term Duₖ §3.2 eq. 5. The code doubles the real part, which the paper does not state (see Paper vs code).
- Apply a gated activation, GELU(y) ⊙ σ(W·GELU(y)), with W a dense H×H layer app. G.1.
Equations as stated in the paper:
\overline{\Lambda} = e^{\Lambda \Delta}, \quad \overline{B} = \Lambda^{-1}(\overline{\Lambda} - I)\tilde{B}, \quad \overline{C} = \tilde{C}, \quad \overline{D} = D eq. 6
x_k = \overline{\Lambda} x_{k-1} + \overline{B} u_k eq. 2, specialised to the diagonal case of §3.2
Pseudocode, following the JAX listing in app. A and the official code:
# S5 layer, one sequence [§3.2] [app. A] [code: s5/ssm.py#L60-L88]
# Inputs: u (L, H) real; Lambda (P,) complex; B_tilde (P, H) complex
# C_tilde (H, P) complex; D (H,) real; log_step (P,) real
# W (H, H) dense; b (H,) dense bias
# Output: (L, H) real
def s5_layer(u, Lambda, B_tilde, C_tilde, D, log_step, W, b):
# Per-mode timescale, log-parameterised [§3.2] [app. B.1.3]
delta = exp(log_step) # (P,)
# Zero-order-hold discretisation of each diagonal mode [§3.2] [eq. 6]
Lambda_bar = exp(Lambda * delta) # (P,)
B_bar = ((Lambda_bar - 1) / Lambda)[:, None] * B_tilde # (P, H)
# Drive term B_bar u_k for every step
drive = u @ B_bar.T # (L, P)
# Linear recurrence x_k = Lambda_bar * x_{k-1} + B_bar u_k,
# computed as a parallel scan [§2.2] [app. H]
states = parallel_scan(linear_op, Lambda_bar, drive) # (L, P)
# Read out the real part of C_tilde x_k [§3.2] [eq. 5]
# The factor 2 is code-only, see Paper vs code
# [code: s5/ssm.py#L86]
ys = 2 * real(states @ C_tilde.T) # (L, H)
# Feedthrough with a diagonal D [§3.2] [eq. 5]
ys = ys + D * u # (L, H)
# Gated activation, half_glu1 variant [app. G.1]
# The dense gate has a bias in the code, not stated in the paper
hidden = gelu(ys) # (L, H)
gate = sigmoid(hidden @ W.T + b) # (L, H)
return hidden * gate # (L, H)Operator for the scan, on pairs (a, b) that stand for the map x ↦ a·x + b app. H:
# Binary operator for the parallel scan [app. H] [code: s5/ssm.py#L46-L57]
# Each element is a pair (a, b) meaning x -> a * x + b, with a diagonal
def linear_op(first, second):
# Compose the earlier element with the later one
a_first, b_first = first
a_second, b_second = second
# Associative, so the scan can be evaluated as a tree [app. H]
return a_second * a_first, a_second * b_first + b_secondInitialisation, following app. B.1:
- Λ starts from the eigenvalues of the diagonalised HiPPO-N matrix, with real part −½ app. B.1.1.
- B̃ = V⁻¹B and C̃ = CV, where B and C are sampled. The paper does not name the distribution app. B.1.2.
- D is sampled from a standard normal app. B.1.2.
- Each Δ element is drawn log-uniformly from [0.001, 0.1], or from [0.0001, 0.1] for Path-X app. B.1.3.
- Optionally, the state matrix is block-diagonal, with J copies of the HiPPO-N block app. B.1.1.
Hyperparameters
Settings shared by every task:
| Name | Value | Where | Notes |
|---|---|---|---|
| Discretisation | zero-order hold | §3.2 eq. 6 | The code also has bilinear, which the paper does not use ssm.py |
| Conjugate symmetry | half the eigenvalues and states | §3.2 | The factor 2 on the readout is code-only. The code halves ssm_size train.py |
| Timescale init | log-uniform in [0.001, 0.1] | app. B.1.3 | Default in code run_train.py |
| Optimiser | AdamW; no weight decay and SSM learning rate on Λ, B̃, Δ | app. G.2.1 | The "standard" group also gives norm parameters the SSM rate train_helpers.py |
| LR schedule | cosine annealing | app. G.2.1 | Warmup is not stated. Code default is 1 epoch of linear warmup run_train.py |
| Normalisation | batch norm and pre-norm for most tasks | app. G.2 | Code defaults run_train.py |
| Bidirectional | on for LRA and speech, off for pendulum and MNIST | app. G.2.2 | Code default is off run_train.py |
| Activation | half_glu1 | app. G.1 | Matches the paper formula layers.py |
| C initialisation | not stated in the paper | app. B.1.2 | Code default is truncated standard normal run_train.py |
Task-specific hyperparameters from app. G.2. The paper's values come first, and the last column compares them with the run scripts in the code. The effective learning rate in the code is the global LR, lr_factor × ssm_lr_base train.py.
| Task | Depth | H | P | J | Dropout | LR | SSM LR | Batch | Epochs | WD | Code check |
|---|---|---|---|---|---|---|---|---|---|---|---|
| ListOps | 8 | 128 | 16 | 8 | 0.0 | 0.003 | 0.001 | 50 | 40 | 0.04 | Matches. Script uses half_glu2 run_lra_listops.sh |
| Text (IMDB) | 6 | 256 | 192 | 12 | 0.1 | 0.004 | 0.001 | 50 | 35 | 0.07 | Values match. Script sets dt_global, half_glu2, no warmup run_lra_imdb.sh |
| Retrieval (AAN) | 6 | 128 | 256 | 16 | 0.0 | 0.002 | 0.001 | 32 | 20 | 0.05 | Matches run_lra_aan.sh |
| Image (LRA) | 6 | 512 | 384 | 3 | 0.1 | 0.005 | 0.001 | 50 | 250 | 0.07 | Script gives 0.0045 (4.5 × 0.001). Also clip_eigs run_lra_cifar.sh |
| Pathfinder | 6 | 192 | 256 | 8 | 0.05 | 0.005 | 0.0009 | 64 | 200 | 0.03 | Script gives 0.0045 (5 × 0.0009) run_lra_pathfinder.sh |
| Path-X | 6 | 128 | 256 | 16 | 0.0 | 0.002 | 0.0006 | 32 | 75 | 0.06 | Script gives 0.0018 (3 × 0.0006). C init is complex_normal run_lra_pathx.sh |
| Speech Commands | 6 | 96 | 128 | 16 | 0.1 | 0.008 | 0.002 | 16 | 40 | 0.04 | Matches. 8 kHz eval rescales Δ by 2.0 run_speech35.sh |
| Pendulum | 4 | 30 | 16 | 8 | 0.0 | 0.012 | 0.003 | 32 | 100 | 0.0 | No pendulum code in the repository |
| sMNIST | 4 | 96 | 128 | 1 | 0.1 | 0.008 | 0.002 | 50 | 150 | 0.01 | MNIST loader present, no run script |
| psMNIST | 4 | 128 | 128 | 2 | 0.15 | 0.004 | 0.001 | 50 | 150 | 0.01 | Permuted MNIST loader present, no run script |
| sCIFAR (colour) | 6 | 512 | 384 | 3 | 0.1 | 0.0045 | 0.001 | 50 | 250 | 0.07 | The paper says it reuses the LRA-image settings. Only the grayscale LRA-image script exists |
Results
Author-reported throughout. Setup: LRA's six tasks, sequence lengths 1,024 to 16,384, and three seeds for S5 and S4 §6.1 app. F.1. Speech Commands 35-way with 16 kHz audio and three seeds §6.2 app. F.2. Pendulum regression on a 24×24 image sequence with 50 irregular samples §6.3 app. G.4. Hardware is a 16 GB V100 for the runtime comparison app. C.2 and an RTX 2080 Ti for the pendulum runs app. F.3.
| Setting | Metric | Baseline | This paper | Source |
|---|---|---|---|---|
| LRA average (6 tasks) | accuracy % | S4-LegS 86.09 | S5 87.46 | tab. 1 |
| LRA ListOps | accuracy % | S4-LegS 59.60 | S5 62.15 | tab. 1 |
| LRA Text | accuracy % | S4-LegS 86.82 | S5 89.31 | tab. 1 |
| LRA Retrieval | accuracy % | S4-LegS 90.90 | S5 91.40 | tab. 1 |
| LRA Image | accuracy % | S4-LegS 88.65 | S5 88.00 (S5 is lower) | tab. 1 |
| LRA Pathfinder | accuracy % | S4-LegS 94.20 | S5 95.33 | tab. 1 |
| LRA Path-X | accuracy % | S4-LegS 96.35 | S5 98.58 | tab. 1 |
| LRA average, O(L²) baseline | accuracy % | Mega 88.21 (quadratic) | S5 87.46 | tab. 1 |
| Speech 16 kHz | accuracy % | S4-LegS 96.08; Liquid-S4 96.78 | S5 96.52 (280K params) | tab. 2 |
| Speech 8 kHz, zero-shot | accuracy % | S4-LegS 91.32; Liquid-S4 90.00 | S5 94.53 | tab. 2 |
| Pendulum regression | MSE ×10⁻³ | CRU (our run) 3.94; CRU reported 4.63 | S5 3.41 (0.27) | tab. 3 |
| Pendulum speed | relative to CRU | CRU 1.0× | S5 86× | tab. 3 |
| sMNIST | accuracy % | S4 99.63 | S5 99.65 | app. F.4 |
| psMNIST | accuracy % | S4 98.70 | S5 98.67 | app. F.4 |
| sCIFAR (colour) | accuracy % | S4 91.80; Liquid-S4 92.02 | S5 90.10 | app. F.4 |
Notes on the table:
- The LRA numbers are means over three seeds, with standard deviations in app. F.1. Across all rows in that table, S5 is highest on Retrieval and Path-X. Mega, which has quadratic cost, is higher on ListOps, Text and Pathfinder. S5 is lower than S4-LegS on Image.
- The paper's own ablation (LRA, app. E): with P = N and a scalar Δ, S5 reaches 57.20 on ListOps and 96.59 on Path-X, against 62.15 and 98.58 for the full model. The state-initialisation ablation app. E shows discrete-time HiPPO-N at 61.93 on Text, against 89.31 for continuous-time HiPPO-N.
- Runtime app. C.2: S5 with P = H trains between 0.7 and 1.9 times as fast as S4D, depending on the task. The configured S5 reaches 4.7 times on Path-X. Memory is 0.7 to 1.2 times S4D.
- Pendulum: S5 takes 0.25 s per training epoch, against 22 s for the authors' re-run of CRU app. F.3. The paper also reports two ablations: S5-drop 6.68 and S5-append 4.13 (lower is better) app. F.3.
Paper vs code
The official code is at github.com/lindermanlab/S5, linked from the paper's introduction §1. It is MIT-licensed and was checked at code_commit.
Discrepancies:
- Learning rate for Pathfinder, Image and Path-X. The table gives LR 0.005, 0.005 and 0.002 app. G.2. The scripts set
lr_factorto 5, 4.5 and 3 times the SSM LR, which gives 0.0045, 0.0045 and 0.0018 run_lra_pathfinder.sh run_lra_cifar.sh run_lra_pathx.sh train.py. The paper's sCIFAR row (0.0045) matches the code, and the paper says sCIFAR uses the LRA-image setting, so the Image row looks like the typo. - "No exceptions to the defaults" for Text. The paper says this app. G.3.2. The IMDB script sets
dt_global,half_glu2andwarmup_end=0run_lra_imdb.sh. - GLU variant. The paper's gate is GELU(y) ⊙ σ(W·GELU(y)) app. G.1, which is
half_glu1layers.py. ListOps and IMDB scripts usehalf_glu2run_lra_listops.sh run_lra_imdb.sh. That variant gates the un-activated y with GELU only in the gate: y ⊙ σ(W·GELU(y)) layers.py. The paper does not mention it. - Path-X output projection. The paper says C̃ = CV app. B.1.2. The Path-X script uses
complex_normal, which samples C̃ directly with no V run_lra_pathx.sh ssm.py. The paper does not state this. - Readout factor 2. With conjugate symmetry, the code returns 2 · Re(C̃x) ssm.py. The paper says only that half the eigenvalues are used §3.2. The factor 2 is needed to match the full-state output. Anyone implementing from the paper alone will be off by a factor of two.
- Meaning of P. The table's P is the full count, ssm_size_base (for Path-X, 256). The code halves it to P/2 complex states train.py. §3.2 states the halving, but the table does not.
- 8 kHz rescaling direction. The paper says to rescale Δ by "the ratio between the new and old sampling rates" §6.2. Read literally, 8 kHz over 16 kHz gives 0.5. The code multiplies by 2.0 train.py, which is old over new. The paper's wording is ambiguous, and the code's direction is the one that doubles the time per sample.
- Warmup. The paper's hyperparameters do not mention warmup. Code defaults to one epoch of linear warmup before cosine annealing run_train.py train_helpers.py.
- Clipped eigenvalues. The LRA-image run sets
clip_eigs=Truerun_lra_cifar.sh, which clips the real part of Λ to at most −1e-4 ssm.py. The paper does not mention this. - Δ in the global group. With
dt_global(IMDB and AAN scripts), the timescale Δ moves from the SSM learning-rate group to the global group, with weight decay train_helpers.py. The paper does not describe this option. - Bidirectional scans. The code runs a forward and a backward scan and concatenates them, so C̃ has 2P columns ssm.py ssm.py. Section 3 describes only the causal model.
- Dropout. The dropout mask is broadcast over axis 0, the time axis of the per-sequence layout, so one mask covers every time step layers.py. The paper does not say this.
- Dense gate bias. The gate layer has a bias layers.py. The paper's W has none.
- Eigenvalue initialisation. The paper says Λ comes from the eigendecomposition of A^Normal app. B.1.1. The code sets the real part to the mean diagonal of S, which is −½, and takes the imaginary parts from
eighon −i·S ssm_init.py. It keeps the first P/2 eigenvalues in ascending order train.py. This picks one member of each conjugate pair, and the paper does not say which.eighassumes a Hermitian matrix and −i·S is not Hermitian, so the code relies on howeighreads the input. I did not verify the eigenvalues numerically. - Abstract rounding. The abstract gives 98.5% on Path-X and the table gives 98.58 tab. 1. Cite the table value.
- Missing code. No pendulum dataset or script is in the repository. There are MNIST and permuted-MNIST loaders dataloading.py dataloading.py, but no run scripts for sMNIST, psMNIST or the colour sCIFAR.
Pitfalls
- Conjugate symmetry has three moving parts: the halved state count, the factor-2 readout, and which half of the eigenvalues to keep. Get all three right, or the output is silently off.
- Parallel scan memory grows as O(P·L) for the stored states, and the paper's runtime claims assume the JAX implementation on a V100 app. C.1 app. C.2.
- Block-diagonal initialisation. With J > 1, the initial Λ repeats the HiPPO-N block. B̃ and C̃ stay dense, and nothing keeps the state matrix block-diagonal during training app. B.1.1.
- Irregular sampling works by passing a different Δ for each step §3.3 §6.3. The pendulum code is not in the repository, so the variable-interval results cannot be reproduced from the code here.
- Speech 8 kHz is a naive decimation of the 16 kHz test set, with Δ rescaled §6.2 app. G.4. It is a zero-shot test of a model trained at 16 kHz, not a retrained model.
- Sampling distributions for B and C are not stated. The code uses lecun-normal for B and truncated-standard-normal for C by default, with complex-normal for Path-X ssm.py run_train.py.
- Optimiser groups. Norm parameters and the SSM parameters are in one group with the SSM learning rate under the default settings train_helpers.py. Changing
opt_configchanges which of B, C and D are decayed, and the paper states only a general rule app. G.2.1.
Lineage
- Builds on: S4 (Gu et al., 2021), for the layer structure, the convolution mode and the HiPPO initialisation. S5 keeps the S4 architecture around the layer and changes the SSM §1 §3.
- Builds on: the diagonal S4D (Gu et al., 2022) and DSS (Gupta et al., 2022) variants. S5 applies their diagonalised HiPPO-N idea to the MIMO setting §4.2.
- Compared against: S4-LegS and S4D-LegS tab. 1 tab. 2; Liquid-S4 (Hasani et al., 2022); Mega and Mega-chunk (Ma et al., 2022); CRU for pendulum regression app. F.3.
- Superseded by: not known from content already in this wiki.
Source and license
Adapted from “Simplified State Space Layers for Sequence Modeling” by Jimmy T. H. Smith, Andrew Warrington, Scott W. Linderman (arXiv:2208.04933), used under CC BY 4.0. Changes: condensed and restructured for implementation, with tables, equations and algorithms taken from the paper and its code, each cited to its source. Not affiliated with or endorsed by the authors. Code citations refer to https://github.com/lindermanlab/S5 at commit 3c18fdb6b064 (MIT). Any quoted code is shown under that license.