State-space models: from linear recurrences to S4 and Mamba
Before this lesson: lesson 07 (convolution), lesson 08 (linear recurrences, spectral radius, gates) and lesson 09 (the cost of attention and the KV cache). Math: the matrix exponential and linear ODEs in linear-algebra lesson 16, circulant matrices and FFT convolution in linear-algebra lesson 19, and eigenvalues in linear-algebra lesson 05. Time: about 80 minutes, plus the notebook. This is a heavy lesson; the folded boxes can be skipped on a first reading.
Why this matters #
Attention costs in the sequence length , and its KV cache grows with every generated token (lesson 09). Many signals are very long: one hour of a seismogram at 100 Hz has 360,000 samples, and attention over it would compare pairs per layer. An SSM trains in parallel, like a CNN or a transformer, and generates one step at a time with constant memory, like an RNN.
The model , is the linear time-invariant system of control theory and of the Kalman filter. S4 (Gu, Goel, Ré 2022) turned it into a deep-learning layer. It was the first model to do better than chance on Path-X, the hardest task of the Long Range Arena benchmark (sequences of 16,384 steps), where earlier models stayed at 50%. Mamba (Gu and Dao 2023) made the parameters depend on the input. It reached transformer quality on language with about 5 times higher generation throughput. Because the model lives in continuous time, is a physical time step: S4 kept about 96% accuracy on speech sampled at half the training rate, without retraining, just by doubling . Interviews ask: "how does Mamba differ from a transformer and from an LSTM?", "why can S4 use an FFT and Mamba not?", "what is a parallel scan?"
1. Predict first #
2. The picture #
The simplest SSM: a leaky integrator #
Take one number: with . The input pushes the state; the term pulls it back to 0. Starting from rest, the solution is
This is an average of the past input with exponentially decaying weights. The memory time is . Engineers call it a leaky integrator or a low-pass filter.
Sample it. Choose a step and keep the input constant during each step. Then the state after each step follows
This is the scalar linear RNN of lesson 08, with . Unrolled, : a convolution of the input with the exponential kernel .
Three views of one map #
The same model can be written in three ways:
- an ODE : the continuous-time parameters, and the meaning of ;
- a recurrence : one step at a time, cheap generation with a fixed-size state;
- a convolution : the whole sequence at once, parallel training with an FFT.
Two computations, one answer. Press Next step a few times. In the recurrence view the state moves one step: . Switch to the convolution view: the violet kernel, flipped, sits under the blue input, with under , and is the sum of the products. The blue dots (recurrence) always sit inside the aqua rings (convolution). The defaults are the worked example of section 4. A larger or a more negative makes the kernel shorter.
A richer kernel from complex eigenvalues #
One real number gives only a decaying exponential. Take a state and a diagonal with eigenvalues . Each mode is a scalar SSM, and the kernel adds them: . A complex gives : a damped oscillation. So the kernel is a sum of damped oscillations. With in the tens, this is a long, structured filter with only parameters. For a real output, modes come in conjugate pairs .
Stability for free. If , then for every . The left half of the complex plane maps into the unit disk, so the recurrence never explodes. This is the spectral-radius problem of lesson 08, solved by the choice of parameters.
Poles, steps and kernels. Drag the violet eigenvalues in the left panel (the faint points are the conjugates). The right panel shows , one step of the recurrence, inside the aqua unit circle. The chart shows the kernel (thick) and each mode's term (dashed). Move a pole to the left: it decays faster. Move it up: it oscillates faster. Raise : every moves toward 0 and the kernel gets shorter in steps. Try one unstable: a pole with maps outside the circle (magenta) and its term grows.
A deep SSM applies one SSM per channel (a depthwise convolution with a kernel as long as the sequence), then mixes the channels with linear layers and nonlinearities. The SSM is linear in its input; the network is not.
The system is discretized with the ZOH and step . What is ?
Over one step with constant input, the state is multiplied by , the exact solution of . The value is Euler's method, a first-order approximation; it is noticeably wrong at this step size. forgets .
3. Definitions and main results #
The continuous model and two discretizations #
Per channel, with input , state and output :
with , , . The term is a skip connection; we drop it in the analysis. The discrete model, in the S4 convention, is
Theorem (zero-order hold, ZOH). If is constant on the -th step of length , then the exact solution of the ODE satisfies the recurrence with
Proof. (The matrix exponential is in linear-algebra lesson 16.)
- By the product rule, .
- Integrate over one step and multiply by : .
- With and the substitution , the integral is .
- If is invertible, , so .
For a scalar : and .
When is not invertible
The integral exists for every ; only the closed form needs . For the integrator it gives . In general, use the series . Or note that, while is constant, the pair solves with , so : one matrix exponential gives both.
Bilinear rule (Tustin; the choice of the original S4). Apply the trapezoidal rule to the state: . Solve for :
For a scalar with : . So the bilinear matches to second order. It also maps the left half-plane into the unit disk, because exactly when .
The two limits of (the key to Mamba). For a stable scalar, , with the ZOH:
- : and . The state is kept and the input is ignored.
- : and . The old state is forgotten; the state jumps to the steady state of the current input.
A stable scalar SSM () is discretized with the ZOH. What does a very large step do at that step?
, so the old state is erased, and , so the state becomes (for ). Stability holds for every because . A small does the opposite: keep the state, ignore the input.
Theorem: the recurrence is a convolution #
With and fixed :
Proof.
- Claim: . For : . ✓
- Step: . Rename in the sum: it becomes , and the last term is the term. So .
- Multiply by : .
The kernel depends only on the lag , because , , are the same at every step. This property is called linear time invariance (LTI). The kernel is the impulse response: the output for the input .
Computing it with the FFT. Direct summation costs . The discrete Fourier transform (DFT) turns a convolution into a product, but a length- DFT gives a circular convolution: the computed would also receive , future inputs wrapped around to the start. The causal convolution is multiplication by a lower-triangular Toeplitz matrix; the length- DFT product is multiplication by a circulant matrix (linear-algebra lesson 19). The fix: pad and with zeros to length at least , multiply the DFTs, invert, and keep the first outputs. The wrapped part then meets only zeros. Cost: per channel.
Why padding is needed. A length-8 DFT product multiplies by this circulant matrix . Each row is the row above, shifted one place to the right with wrap-around. Its upper-right corner is the wrap-around: these entries make early outputs use late inputs. A causal SSM kernel needs only the lower triangle; padding to length pushes the wrap-around into rows that we throw away.
Two modes of the same layer. For training, the whole sequence is known: compute once and convolve in parallel with the FFT. For generation, run the recurrence: work per step for a diagonal , and only the state is stored.
Stability by parametrization. If every eigenvalue of has , then every eigenvalue of has , for every . So and : the kernel decays. Models enforce this by storing the real part as with a free parameter , so training can never make it positive.
S4: why needs structure #
Initialization matters. A random works badly: the state forgets quickly and keeps no useful summary. The S4 paper reports that changing from random to the HiPPO matrix took an earlier SSM on sequential MNIST from 60% to 98% accuracy. The HiPPO-LegS matrix is
HiPPO derives so that the state holds the coefficients of an approximation of the input history by Legendre polynomials: the state is an online, compressed summary of the whole past. (The time-invariant form used in S4 weights the past with exponentially warped Legendre polynomials; Gu et al. 2022, "How to Train Your HiPPO".)
The cost problem. Computing naively needs products with an matrix: work. A diagonal would make it cheap: then , work. A change of basis gives the same map, , so why not diagonalize HiPPO? Because its eigenvector matrix is extremely ill-conditioned (S4, Lemma 3.2): with the natural scaling, its entries grow like . In floating point the diagonalization is useless:
| eigenvalues of HiPPO-LegS | condition number of the eigenvector matrix | |
|---|---|---|
| 4 | ||
| 8 | ||
| 16 | ||
| 24 | (the limit of float64) |
The matrix is lower triangular, so its eigenvalues are the diagonal entries . The trouble is only in the eigenvectors, which are nearly parallel (linear-algebra lesson 05).
S4's answer: normal plus low rank
HiPPO-LegS can be written as with unitary, diagonal and of rank 1 (normal plus low rank, NPLR). A unitary change of basis is perfectly conditioned. S4 then computes the DFT of the kernel from the resolvent at the roots of unity . It removes the low-rank term with the Woodbury identity, reduces the diagonal part to a Cauchy kernel, and inverts the DFT with an FFT: work.
Diagonal SSMs. DSS (Gupta et al. 2022) and S4D (Gu et al. 2022) simply drop the low-rank term and use a diagonal . S4D proves that the normal part of HiPPO-LegS alone gives the same kernel as ; the kernel computation is then two lines of code. Common initializations: S4D-Lin, (damped Fourier modes), and S4D-Real, (Mamba's default). The real part is stored as , so it stays negative.
A trained S4 layer (fixed ) is used to train on long sequences and then to generate text. Which form is used where?
During training the whole input is known, so the kernel is computed once and the FFT convolution handles all positions in parallel. During generation the inputs arrive one at a time, so the recurrence does work per token with a state of fixed size. Recomputing a convolution for every new token would cost per token.
Mamba: selection makes the model time-varying #
The limit of LTI. One fixed kernel weights each input by its distance in time, never by its content. Gu and Dao show the failure on selective copying: copy the coloured tokens, which sit at random positions between noise tokens. An S4 layer without gating reaches 18.3%; its selective version (S6) reaches 97.0%.
The selective SSM (S6). Per channel and per state index, the state follows , but now the parameters depend on the current input. With channels and state size per channel:
- and , shared by all channels;
- , one step size per channel (a low-rank projection in practice); softplus is , a smooth positive function;
- stays a parameter (diagonal for each channel), but now depends on ;
- per channel: , .
The paper uses the ZOH. The reference code uses the ZOH for and Euler, , for (" is the more important term").
Theorem (Mamba, Theorem 1: selection generalizes gating). Take , , and with . Then the ZOH recurrence is
where is the logistic sigmoid.
Proof.
- .
- .
This is the gate of the GRU in lesson 08, derived from discretization. A small ignores the token and keeps the memory; a large resets the state to the token. Resetting also stops separate documents, packed into one training sequence, from leaking into each other.
Selection by hand. Each token has an input and a logit (slider); . The yellow bars show the gate , the blue line the state. In the worked example the large input gets , a tiny , and is mostly ignored: its weight in the last state is 0.024. Try reset at token 4: one large copies into the state, and the very negative after it keep it. With same z the weights depend only on the distance to the end, as for a fixed kernel.
Why the convolution view is lost. Unroll the recurrence (per channel and state index):
The weight of depends on , on and on all inputs in between, not only on the lag . There is no single kernel, so there is no FFT.
Why can Mamba not compute its kernel once and use an FFT, as S4 does?
A convolution needs one kernel that depends only on the lag. In Mamba the weight depends on the inputs between and . The recurrence is still linear in the state (the nonlinearity is only in how the parameters are computed), and this is exactly what the scan below uses. is diagonal in Mamba.
Theorem: the associative scan #
The recurrence (elementwise; , ) is linear in . Read as the affine map , and define "first , then ":
Then maps to . With , the state is its second component.
Check with numbers. and . The loop gives and . The operator gives , and its second component is . ✓
Theorem. is associative: .
Proof.
- Write as the matrix . It maps to .
- "First , then " is the product : .
- Matrix multiplication is associative, so is associative. It is not commutative: order matters.
Parallel prefix. Associativity lets us regroup the long product into a tree, and the nodes of one level of the tree can be computed at the same time.
- Hillis–Steele: for , replace every with by , all at once. Depth rounds, work combines.
- Blelloch: an up-sweep (a tree of totals) and a down-sweep (prefixes passed down the tree). Depth about rounds, work combines.
A scan for . Each box shows which elements it has combined: "2–5" means . Press Next round: the combines of the round are yellow. Hillis–Steele needs 3 rounds () and 17 combines. The sequential loop needs 7 rounds and 7 combines. Blelloch needs more rounds but only combines. The last row is , and it equals the plain loop.
A scan needs each step to stay in a family of maps that is closed under composition. Affine maps are closed: composing two gives another one, stored as one pair . The map is not closed: composing two tanh steps gives a new kind of function that no fixed-size pair can store. So a tanh RNN stays sequential. A diagonal keeps the combine elementwise; a dense one would need matrix products in every combine.
The Mamba block and the hardware-aware scan
The block. Project the input to two branches of width (). Branch 1: a short causal depthwise convolution (kernel 4), SiLU, the selective SSM. Branch 2: SiLU, used as a gate. Multiply the branches and project back to . Most parameters sit in the projections, per block, so two Mamba blocks match the of one transformer layer (attention plus MLP).
The kernel. The expanded state has shape (batch, , , ), times larger than the input. Mamba's fused GPU kernel loads , , , into fast on-chip memory (SRAM), discretizes, scans and multiplies by there, and writes only back to the main GPU memory (HBM). This saves a factor of about in memory traffic; the paper reports 20–40 times faster than a plain scan. The backward pass recomputes the states instead of storing them. Long sequences are scanned in chunks, and the state is carried from chunk to chunk.
How many parallel rounds does the Hillis–Steele scan need for , and how many combines in total?
The shift doubles each round (), so there are rounds. Round updates every , that is elements, and . The sequential loop needs 1023 rounds of one combine each: less work, much more depth.
Costs #
Per layer, for length , width and state size (the linear projections, , are common to all):
| Training | Per generated token | Stored for generation | |
|---|---|---|---|
| Attention | KV cache, | ||
| S4 (LTI) | with the FFT | state, | |
| Mamba | work, depth with a parallel scan | state, (plus a short convolution buffer) |
The price of the fixed state: it must compress the whole past, so exact recall from a long context is weaker than with attention. Hybrid models keep a few attention layers; Jamba, for example, uses one attention layer for every seven Mamba layers.
Answers to section 1. (1) The SSM stores numbers per layer, whatever is. The KV cache stores , about 125,000 times more. (2) In general, no. A fixed kernel can only weight inputs by their distance, and here the distance is random. This is the selective-copying failure that motivated Mamba. (3) No. Tanh steps are not closed under composition, so there is no fixed-size combine operator; a tanh RNN must run step by step.
4. Worked example #
(a) Discretize , (so , ) with , so .
- ZOH: and .
- Bilinear: and . Close to the ZOH.
- Euler for (Mamba's code): , which is 27% larger than the ZOH value at this step.
(b) Kernel (ZOH). : , , .
(c) Recurrence = convolution for the input :
- recurrence: ; ; ;
- convolution: . ✓
(d) Selection by hand (the Theorem 1 system). Logits and inputs .
- and .
- .
- .
- .
- The large input got a tiny and was mostly ignored.
- The weights in : gets , gets , gets . An LTI model would give a weight that depends only on its lag, 2.
(e) Counting a scan for : Hillis–Steele needs 10 rounds and combines; Blelloch about combines in about 20 rounds; the loop 1023 combines in 1023 rounds.
5. In code #
SciPy does the discretization, the recurrence and the convolution, so you can check the worked example and the theorem. The notebook builds each piece from scratch.
import numpy as np
from scipy.signal import cont2discrete, dlsim, fftconvolve
# (a) x' = -2x + u, y = x, step 0.25
A, B, C, D = np.array([[-2.0]]), np.array([[1.0]]), np.array([[1.0]]), np.array([[0.0]])
for method in ["zoh", "bilinear"]:
Ab, Bb, Cd, Dd, _ = cont2discrete((A, B, C, D), 0.25, method=method)
print(method, Ab.item(), Bb.item(), Cd.item(), Dd.item())
# zoh 0.6065306597126334 0.1967346701436833 1.0 0.0
# bilinear 0.6 0.2 0.8 0.1 <- SciPy also changes C and D for 'bilinear'; S4 keeps C
# recurrence = convolution for a random stable system with N = 4
rng = np.random.default_rng(0)
N, L = 4, 256
A = -np.diag(np.arange(1.0, N + 1)) + 0.5 * rng.standard_normal((N, N))
B, C = rng.standard_normal((N, 1)), rng.standard_normal((1, N))
print(np.linalg.eigvals(A).real.max() < 0) # True: stable
u = rng.standard_normal(L)
impulse = np.zeros(L); impulse[0] = 1.0
for method in ["zoh", "bilinear"]:
Ab, Bb, *_ = cont2discrete((A, B, C, D), 0.1, method=method)
# S4: x_k = Ab x_{k-1} + Bb u_k, y_k = C x_k. dlsim uses s_{k+1} = Ab s_k + Bb u_k,
# y_k = C' s_k + D' u_k, so take s_k = x_{k-1}, C' = C Ab and D' = C Bb.
sys = (Ab, Bb, C @ Ab, C @ Bb, 0.1)
y_rnn = dlsim(sys, u)[1].ravel() # recurrent mode
K = dlsim(sys, impulse)[1].ravel() # kernel = impulse response
y_cnn = fftconvolve(u, K)[:L] # convolutional mode (padded FFT)
print(method, np.abs(np.linalg.eigvals(Ab)).max() < 1, f"{np.abs(y_rnn - y_cnn).max():.0e}")
# zoh True 5e-17
# bilinear True 7e-17
Why the FFT needs padding, and why S4 does not just diagonalize HiPPO:
from scipy.linalg import circulant, toeplitz
L = 6
K = 0.6 ** np.arange(L)
T = toeplitz(K, np.zeros(L)) # causal: y = T u uses u_0..u_k only
Cm = circulant(K) # a length-L DFT product multiplies by this
print(np.allclose(np.tril(Cm), T), np.abs(np.triu(Cm, 1)).max()) # True 0.6: future inputs leak in
print(np.allclose(circulant(np.r_[K, np.zeros(L)])[:L, :L], T)) # True: padding fixes it
def hippo_legs(N):
n = np.arange(N)
A = -np.sqrt((2 * n[:, None] + 1) * (2 * n[None, :] + 1))
return np.tril(A, -1) - np.diag(n + 1.0)
for N in [4, 8, 16, 24]:
lam, V = np.linalg.eig(hippo_legs(N))
print(N, lam.real.max(), lam.real.min(), f"cond(V) = {np.linalg.cond(V):.0e}")
# 4 -1.0 -4.0 cond(V) = 9e+01
# 8 -1.0 -8.0 cond(V) = 8e+04
# 16 -1.0 -16.0 cond(V) = 8e+10
# 24 -1.0 -24.0 cond(V) = 9e+16
Mamba's Theorem 1 and the two limits of :
z = np.linspace(-6, 6, 13)
delta = np.logaddexp(0, z) # softplus(z) = log(1 + e^z)
A_bar = np.exp(-delta) # ZOH with A = -1
B_zoh = 1 - np.exp(-delta) # ZOH for B (B = 1)
g = 1 / (1 + np.exp(-z))
print(np.allclose(A_bar, 1 - g), np.allclose(B_zoh, g)) # True True
for i in [0, 6, 12]: # z = -6, 0, 6
print(f"z={z[i]:+.0f} Delta={delta[i]:.4f} A_bar={A_bar[i]:.4f} B_zoh={B_zoh[i]:.4f}")
# z=-6 Delta=0.0025 A_bar=0.9975 B_zoh=0.0025 keep the state, ignore the token
# z=+0 Delta=0.6931 A_bar=0.5000 B_zoh=0.5000
# z=+6 Delta=6.0025 A_bar=0.0025 B_zoh=0.9975 reset the state to this token
6. Where it shows up #
- Long sequences. S4 and S4D for long-range benchmarks, raw audio (16,000-step speech; SaShiMi for audio generation) and medical time series. H3 and Hyena are convolutional relatives.
- Language and biology. Mamba for language, DNA and audio; in the paper, Mamba-3B matches transformers of twice its size. Mamba-2 (Dao and Gu 2024) restricts to a scalar times the identity. This links the selective SSM to masked linear attention and lets it run on matrix multiplications. Hybrid language models such as Jamba mix Mamba, attention and mixture-of-experts layers.
- ML for science. Long, densely sampled records: seismograms, EEG and ECG, climate and weather station series, genomes. The continuous-time view fits physical data: can follow the sampling rate, so the same weights can serve sensors with different rates. is also the linear Gaussian state-space model of data assimilation (the Kalman filter), and a learned linear evolution in a lifted state is close to Koopman-operator models. A deep SSM is a natural backbone for long waveforms, or the temporal part of a spatio-temporal emulator.
- Practice. The official kernels are in the
mamba_ssmpackage.mamba-minimalis a short PyTorch reference with a sequential loop, useful for reading.
7. Common mistakes #
- No zero padding in the FFT. A length- FFT gives a circular convolution: future inputs leak into early outputs. Pad to at least .
- Inverting for the ZOH. fails for a singular ; the integral (series or block exponential) always works.
- as "the" discretization. This is Euler, accurate only for . The ZOH and bilinear depend on .
- Comparing with SciPy's bilinear and .
cont2discrete(..., method="bilinear")rescales and adds a . S4's and match SciPy; its does not change. - "Mamba makes input-dependent." is a parameter; depends on the input only through .
- "An SSM trains sequentially because it is an RNN." LTI models train as convolutions, selective models with a parallel scan.
- "Any RNN can use a parallel scan." Only if each step lives in a family closed under composition, such as affine maps. Not a tanh RNN.
- Diagonalizing HiPPO in floating point. The eigenvectors are exponentially ill-conditioned. Use NPLR, or a diagonal initialization such as S4D-Lin or S4D-Real.
- Letting become positive. The kernel then grows exponentially. Parametrize .
8. Check yourself #
- The integrator (, ). Give the ZOH and .
Answer
and . The closed form is undefined, but its limit as is also . - , and you multiply length-8 FFTs of and without padding. What does the computed contain?
Answer
: the circular sum adds seven terms with future inputs. The correct is . - An S4D-Lin mode has and . What is , after how many steps has the mode
decayed by half, and what is its period in steps?
Answer
. Half-life: steps. Period: steps. - In the Theorem 1 system, which gives the gate ?
Answer
, so . It comes from , because . - S4 is trained on speech at 16 kHz. How do you run it at 8 kHz without retraining?
Answer
Double . The samples are now twice as far apart in time, , and the continuous parameters , , stay the same. - Why can Mamba not compute its kernel once and use the FFT, as S4 does?
Answer
, , change with , so the weight of in is . It depends on and on the inputs between them, not on alone. There is no shared kernel.
Write the continuous SSM and its discrete recurrence (S4 convention).
, ; discrete: , .
Give the ZOH discretization of with step .
and for invertible .
Compute the ZOH and for with .
and .
What is the convolution kernel of an LTI SSM?
, so . It is the impulse response.
Why must you zero-pad before computing the SSM convolution with an FFT?
A length- DFT product is a circular convolution, so future inputs wrap around into early outputs. Padding to removes the wrap-around.
Why is an SSM with stable for every step size?
The eigenvalues of are , with for all .
Why does S4 not simply diagonalize the HiPPO matrix?
Its eigenvector matrix is exponentially ill-conditioned (about already at ), so the diagonal form is useless in floating point. S4 uses normal plus low rank instead.
What does "selection" mean in Mamba?
, and are computed from the current input, so the model decides per token whether to keep its state (small ) or reset it to the token (large ).
Give the scan operator for and say why it allows a parallel scan.
. It is associative (a product of matrices), so prefixes can be computed in a tree of depth .
What does an SSM store per layer to generate the next token, compared with attention?
The state, numbers, independent of ; attention stores the KV cache, numbers.
9. Interview angle #
- "Explain Mamba in two minutes." — A linear recurrence with a diagonal state per channel whose , , come from the input (selection = learned gating), computed by a fused parallel scan; linear-time training and constant-memory generation.
- "S4, Mamba and attention: what are the costs?" — The table in section 3: against against for training; a KV cache of against a state of for generation.
- "Why does S4 need HiPPO and structure?" — A random forgets; HiPPO compresses the history; the NPLR or diagonal forms make the kernel cheap and stable to compute.
- "What is a parallel scan?" — The affine-map operator is associative, so the prefixes form a tree of depth .
- "When would you still use attention?" — For exact retrieval and copying from a long context (in-context recall); hence hybrid models.
10. Practice #
The notebook for this lesson runs in Colab (NumPy and SciPy only). It has five exercises, each with a check cell and a folded solution:
- Write the ZOH and bilinear discretizations and check them against
scipy.signal.cont2discrete. - Compute a random stable diagonal SSM as a recurrence and as an FFT convolution, and show that they agree up to rounding error (below ).
- Write the scan operator, a sequential scan and a Hillis–Steele scan, and show that they give the same states.
- Write a Mamba-style selective scan with and check it against a naive loop and against the gate form of Theorem 1.
- Build the HiPPO-LegS matrix and measure the condition number of its eigenvectors as grows.
11. Watch and read #
- Gu, Goel, Ré, Efficiently Modeling Long Sequences with Structured State Spaces (S4): §2 (the three views, HiPPO, the bilinear rule, the kernel), §3 (why not diagonalize, NPLR, complexity), §4 (results, including the sampling-rate change).
- Rush and Karamcheti, The Annotated S4: the discrete SSM, the convolution, HiPPO and the diagonal case, in code.
- Gu, Gupta, Goel, Ré, On the Parameterization and Initialization of Diagonal State Space Models (S4D): S4D-Lin and S4D-Real.
- Gu and Dao, Mamba: Linear-Time Sequence Modeling with Selective State Spaces: §3.1–3.3 (selection, the scan, the fused kernel), §3.5 (Theorem 1).
- Dao and Gu, Transformers are SSMs (Mamba-2): the link between selective SSMs and linear attention.
- Guy Blelloch, Prefix Sums and Their Applications: the work-efficient scan.
mamba-minimal: a short, readable PyTorch Mamba (ZOH for , Euler for inselective_scan).
Runs in your browser with nothing to install. The notebook repeats the key demos and has exercises with checks; solutions are inside, folded.
No Google account needed: Python runs inside your browser. The first start downloads about 40 MB; your changes are saved in this browser only.