Gated KronLSTM Sequence Mixer
Recurrent linear attention needs controlled memory updates; KronLSTM separates forgetting, erasing, and writing into gates inside a standard sequence-mixer block.
What it is
- Separate memory controls KronLSTM uses distinct gates to forget old memory, erase a key-matched response, and choose how much new value to write.
- Key-direction forgetting A vector gate can fade different key directions by different amounts, instead of shrinking the whole memory uniformly.
- Gated readout A query reads from the memory, and an output gate controls how much of that result reaches the next layer.
Why it matters
The block makes memory editing more explicit while keeping its recurrent state to the head memories themselves, without extra normalizer or stabilizer memories.
Before getting into the mechanics, here is the short version: KronLSTM is a recurrent attention layer with a matrix memory and several gates that get different jobs. It can fade old associations, erase the old response to a key, write a chosen value, and decide how much of the readout to pass onward. That separation makes the update easier to reason about than asking one knob to do everything.
-
Update control: A memory update has to deal with old content and new content at once. The canonical example is a notebook entry for a key: you may want to stop carrying the old answer, write a replacement, or simply let the entry fade. Those are related decisions, but not identical ones. The notebook analogy breaks because this memory changes continuously through vector and matrix operations, not discrete edits.
-
Direction-specific retention: A single decay for the whole memory treats every stored association alike. KronLSTM instead lets retention vary by key direction, so some kinds of cues can persist while others fade. This is like deciding what not to carry to the next town—but the gate acts on learned directions, not named facts.
-
Simple recurrent bookkeeping: Linear-attention layers need a state that can be updated and queried as tokens arrive. KronLSTM's block carries the head memories, without additional normalizer or stabilizer memories. That is a statement about state structure, not a guarantee that every implementation is automatically cheap or simple.
So how does the layer keep those decisions apart? Start with the familiar idea of a memory prediction error: query the memory with the current key to see what it already associates with that key, then correct that response toward a target. The erase gate sets how strongly that correction acts; the write gate scales the target value. In notation, the target is written as . In words, the target is adjusted so the correction strength and written amount can be separate controls. Both gates are input-driven sigmoid scalars for each head.
What about forgetting before the correction? Instead of fading the entire notebook equally, KronLSTM applies a vector of retention values along the key dimension. Formally, , so the memory is multiplied by this diagonal matrix on its right. In words, each key direction gets its own retention amount before the key-matched edit happens. The vector comes from a sigmoid projection raised componentwise to a learned positive per-head power; the input varies retention by direction, while the power tunes the head's overall timescale.
The canonical example for the read is a lookup: the current query asks the stored key-to-value associations for a result. The memory read is . In words, the query weights the stored key directions and produces a value-space vector. A sigmoid output gate then controls how much of that vector proceeds through per-head normalization and the output projection. This gate controls the emitted read, not the memory update.
So why call it a sequence-mixer block rather than just an update rule? The layer also builds queries, keys, and values from input projections, short causal depthwise convolutions, and SiLU activations; queries and keys are L2-normalized. With normalized keys and values and a sigmoid erase gate, each update is non-expansive, and the forget gate contracts memory further. The design therefore joins a familiar block interface to a recurrent matrix memory. What remains open is whether this division of labor is the right tradeoff for a particular model and task.
Read the deep dive
Why People Wanted It
A recurrent memory update has to decide what to retain, what old association to erase, and what new association to write. If one gate is made to do several of those jobs, the controls are coupled: changing how much new information is written can also change how much old information gets removed. The practical question is whether a linear-attention block can expose these decisions separately while keeping its recurrent state simple.
KronLSTM takes the Kronecker Delta memory rule and embeds it in a gated sequence-mixer block. The block carries its head memories, rather than extra normalizer or stabilizer memories.
The Core Move
The core move is to give forgetting, erasing, and writing separate controls, then query the resulting matrix memory.
For one head, let be memory, with key , value , and query . Its update is
where forgets along key directions, controls erasure, and the target controls writing through the parameterization described below. The read is .
Why Erase and Write Need Separate Gates
Now the version for readers who want more of the machinery: the key distinction is that the update can correct the decayed memory toward a gated target rather than forcing the target to be one. Let the desired target be . Substituting this into the correction form gives
In words, the erase amount remains set by , while the value contribution is scaled by . Both gates are per-head scalars computed from the input with sigmoid projections, so each is bounded; they are not two names for one shared knob. This is the architectural separation: forgetting first acts on memory, then the key-directed correction erases the existing response and writes the gated target.
Why Forgetting Acts Per Key Direction
Here is the part that gets technical: the forget operator is diagonal on the key dimension, so it can retain different memory directions by different amounts. Write , with each component strictly between zero and one. The update multiplies memory on the right by , meaning each key direction is independently attenuated before the correction.
The forget vector is parameterized as , with the exponent applied componentwise and one learned scalar per head. In words, the input sets direction-specific retention, while the learned positive power adjusts the head's overall retention horizon. This is not a value-channel forget gate: its diagonal spans key directions, and the matrix memory is contracted from the right.
Why the Readout Is Gated Without Extra Memory
Now the block-level detail: queries, keys, and values come from input projections followed by short causal depthwise convolutions and SiLU activations; queries and keys are L2-normalized. The memory read is , which means the query selects a value-space output from the stored key-to-value associations.
A sigmoid output gate modulates that read, followed by per-head RMSNorm and an output projection over concatenated heads. The gate changes what the current layer emits; it is not another recurrent memory. The block's recurrent state consists of the head memories , with no separate normalizer or stabilizer state. So what does this simpler state bookkeeping buy, and what does it leave the gates responsible for?
Minimal Causal Code
This loop makes the memory update visible. It omits the projections, convolutions, normalization, and output gate that wrap the rule in the full block.
import torch
def kronlstm_step(S, k, v, q, F, beta, c):
# S: [value_dim, key_dim]; F: [key_dim]
decayed = S * F.unsqueeze(0)
predicted = decayed @ k
error = c * v - predicted
S_next = decayed + error.unsqueeze(-1) * k.unsqueeze(0)
read = S_next @ q
return S_next, read
The vector F scales each key column of S; beta is omitted from this compact expression because the write target is represented directly as c in the decoupled update. In the equivalent target form, the correction is scaled by beta and targets c / beta.
What You Gain, and What You Lose
The gate roles are explicit: a per-key-direction forget gate contracts memory, while separate per-head erase and write gates control the correction, and an output gate controls the read. The full block uses only its head memories as recurrent state, with no additional normalizer or stabilizer memories. With L2-normalized keys and values and sigmoid , the update is non-expansive; the forget gate contracts it further.
The cost is that you now have several input-dependent controls to parameterize and reason about, rather than one coupled update knob. The forget gate only distinguishes key directions, while erase and write gates are scalar per head; the output gate controls emission, not stored memory. KronLSTM is thus not a claim that every gate can express every kind of memory edit. It is a design that assigns distinct jobs to distinct gates.
KronLSTM gives forgetting, erasing, writing, and reading distinct controls around one recurrent matrix memory.