From Signal Flows to Hyper-Vectors: Building a Lean LMU-RWKV Classifier with On-the-Fly…
“If you can’t fit the table in memory, throw the table away.” — A practical engineer, probably
From Signal Flows to Hyper-Vectors: Building a Lean LMU-RWKV Classifier with On-the-Fly Hyper-Dimensional Hashing
“If you can’t fit the table in memory, throw the table away.” — A practical engineer, probably
Overview
Multi-kilobyte word embeddings and multi-gigabyte language models have become the status-quo for NLP, yet there is an alternative lineage whose intellectual roots run through cognitive science, control theory and even the mathematics of random projection.
In this post we walk, line-by-line, through a 4-component text-classifier I built that:
- Extracts features with an LMU — a Linear Memory Unit derived from control-theoretic systems that yields provably optimal continuous-time memory kernels.
- Mixes temporal context with a micro-RWKV stack — a recurrent form of the popular RWKV architecture that keeps sequence-length scaling at O(T) instead of O(T²).
- Hashes every token into a binary ±1 hyper-vector on the fly, avoiding the V×DV\times DV×D lookup table entirely.
- Combines dense LMU/RWKV features with a bundled hyper-vector in a bind-and-bundle head to yield a single log-odds scalar.
On commodity Colab hardware, the entire model — including vocabulary building, training on 150 000 Yelp reviews, and evaluation — fits comfortably under 4 GB of VRAM. The final binary classifier handles sequences up to 256 tokens, manages +/- ~90 % validation accuracy (depending on hyper-parameters), and most importantly demonstrates how far we can stretch small-model design when we lean on clever mathematics rather than parameter brute-force.
1 · Mathematical Foundations (≈1 050 words)
1.1 Linear Memory Units in Continuous Time
The LMU starts with a linear time-invariant (LTI) system written in state-space form

1.2 RWKV as a Convolutional Recurrent Kernel
The (much larger) transformer-sized RWKV architecture replaces quadratic self-attention with a time-decaying weighted-key accumulator. In the cell form we write

1.3 Hyper-Dimensional Computing and Majority Bundling

1.4 Bind-and-Gate Head

2 · Code Walkthrough
The complete Python script is below, I will trace the critical pieces.
2.1 Vocabulary Builder
def build_vocab_ds(samples=150_000, min_freq=2, top_k=30_000):
ds_iter = load_dataset("yelp_polarity", split="train", streaming=True)
counter = Counter()
for ex in tqdm(itertools.islice(ds_iter, samples)):
counter.update(tokenize(ex["text"]))
return Vocab(counter, min_freq, top_k)
- Streams raw datasets rows → zero RAM blow-up.
- Stops at samples for quick prototyping.
- Keeps exactly 30 k-2 tokens over
min_freq, plus<pad>and<unk>.
2.2 Token → Hyper-Vector Hash
class HyperDimensionalSpace:
_MUL = 6364136223846793005
_INC = 1442695040888963407
def lookup(self, tokens):
t = tokens.unsqueeze(-1).long()
pos = torch.arange(self.dim, device=tokens.device)
bits = (t * self._MUL + pos + self._INC) & 1
return torch.where(bits.bool(), 1., -1.)
No torch.nn.Embedding, no Megabyte matrix. Lookup is O(T·D) element-wise integer math, broadcast on GPU.
2.3 LMU Forward Loop
m = torch.zeros(B, order, device=x.device)
l_out = []
for t in range(T):
h, m = self.lmu(e[:, t], m)
l_out.append(h)
The cell returns hidden projection + new memory. Only order (12) floats persist between time-steps—far cheaper than full-sequence activations.
2.4 RWKV Stack
r = self.rwkv(torch.stack(l_out, 1)) # (B,T,H)
seq = (r * mask[..., None]).sum(1) / lengths[:, None]
The stack processes the entire time-axis in Python space, but each cell loops internally for clarity. Replace with a CUDA-accelerated fused kernel if you need speed; correctness matches the official RWKV recurrence.
2.5 Bind-and-Bundle Head
dense = torch.tanh(self.to_hd(seq)) # (B,D)
token_vecs = self.hd.lookup(x) # (B,T,D)
bundled = HyperDimensionalSpace.bundle(token_vecs * mask[..., None])
hd = bundled * torch.sign(dense) # (B,D)
return self.head(hd).squeeze(1) # (B,)
Five lines, no gigantic parameters, yet surprisingly expressive. Rough timing: 2 ms for 64×256 inference on a T4 GPU.
2.6 Training Loop with Visible Progress
for ep in range(1, epochs+1):
tr = run_epoch(model, train_dl, opt, True, device, f"Epoch {ep} [train]")
te = run_epoch(model, test_dl, opt, False, device, f"Epoch {ep} [eval]")
print(f"Epoch {ep}: train loss {tr[0]:.3f} acc {tr[1]:.3f}"
f" | eval loss {te[0]:.3f} acc {te[1]:.3f}")
Both train_dl and test_dl share the pad_collate to guarantee fixed-length tensors; release memory with del if you chain multiple experiments.
3 · Practical Use-Cases
3.1 On-device sentiment monitoring
Binary ±1 head + small parameter count (<5 M) fits into mobile VRAM; hashing avoids loading any token table.
3.2 Privacy-sensitive e-mail triage
Deterministic hashing means deployed binaries can recreate vectors without shipping pretrained embeddings — no leakage risk.
3.3 Real-time moderation pipelines
O(T) forward pass, no attention matrix; stable latency at T=512 even under load spikes.
3.4 Edge-gateway anomaly detection
Replace Yelp polarity with log lines; LMU handles long-range numeric patterns, hyper-bundle aggregates categorical tokens.
3.5 Few-shot active learning
Small parameter footprint speeds fine-tuning cycles; one can freeze LMU + RWKV and only retrain head on 1–5 % labelled data.
4 · Benefits & Trade-offs
4.1 Benefits
- Memory Efficiency
No V×DV\times DV×D matrix (≈240 MB for 30 k×2 048
float32). The entire model—including optimizer —uses <40 MB. - Deterministic Symbolic Space Hash mapping is fixed; deploying new tokens merely re-hashes them. This decouples the front-end tokenizer from training artifacts.
- Provable Long-Term Memory LMU’s continuous-time derivation ensures error ≤ ε regardless of sequence length, unlike truncated RNNs.
- Stable Gradient Flow LMU matrices form an orthogonal basis; RWKV’s decay gate prevents recurrent explosion; hyper-vector ops are sign-only.
- Interpretable Binary Head Post-training, inspecting www reveals which hyper-dimensional axes carry signal; one can correlate them back to token clusters.
4.2 Trade-offs
- Hash Collisions
Though theoretically low, two semantically opposite tokens might land on correlated hyper-vectors; mitigation = increase
--hd-dim. - Loss of Sub-token Detail We tokenize on whitespace+punct; languages with rich morphology may need BPE plus an extra hashing salt.
- Throughput vs. CUDA Kernels The pure-Python RWKV recurrence is illustrative; in production you’d JIT a fused kernel for 10× throughput.
- Binary Head Softness
Hard sign gating is non-differentiable; we rely on straight-through gradient through
torch.sign. Works fine empirically, but optimisation landscape may be choppy.
6 . Notebook
[embed]Google Colab Edit descriptioncolab.research.google.com
7 · Conclusion
This walk-through shows that a truly small neural text-classifier need not sacrifice sophistication. By fusing a control-theoretic memory kernel (LMU), a modern decay-based context mixer (RWKV), and an information-dense hyper-dimensional allocator, we achieve solid Yelp polarity accuracy with orders of magnitude fewer parameters than mainstream transformer baselines.
While the exact code is tailored for binary sentiment, the pattern generalises:
- Replace the datasets stream. Point to any sentence-label pair; tokeniser stays the same.
- Tune
--hd-dim. Regression tasks fare better with 4 096 or 8 192 bipolar dimensions. - Swap the head. Multi-class? Make
head = nn.Linear(D, C)and feed toCrossEntropyLoss. - Scale the stack. For rare long-range tasks up the RWKV layers to 4–6; VRAM cost grows linearly.
Most importantly, you now own an idiomatic PyTorch template free of compiled TorchText baggage, free from 2-D attention quadratics, and free from parameter bloat — yet rich in mathematics.
So the next time you need a fast, private, and memory-lean NLP model, consider throwing the giant table away and letting a hash function, a Legendre delay line, and a decayed key accumulator do the heavy lifting.

Thank you for being a part of the community
Before you go:
- Be sure to clap and follow the writer ️👏️️
- Follow us: **X | [LinkedIn](https://www.linkedin.com/company/inplainenglish/) | [YouTube](https://www.youtube.com/@InPlainEnglish) | [Newsletter](https://newsletter.plainenglish.io/) | [Podcast](https://open.spotify.com/show/7qxylRWKhvZwMz2WuEoua0) | [Differ](https://differ.blog/inplainenglish) | [Twitch](https://twitch.tv/inplainenglish)**
- **Start your own free AI-powered blog on Differ** 🚀
- **Join our content creators community on Discord** 🧑🏻💻
- For more content, visit **plainenglish.io + [stackademic.com](https://stackademic.com/)**
메타데이터
- post_id
- f8e2ffc03e7c
- slug
- from-signal-flows-to-hyper-vectors-building-a-lean-lmu-rwkv-classifier-with-on-the-fly-f8e2ffc03e7c
- url
- https://python.plainenglish.io/from-signal-flows-to-hyper-vectors-building-a-lean-lmu-rwkv-classifier-with-on-the-fly-f8e2ffc03e7c
- canonical_url
- https://python.plainenglish.io/from-signal-flows-to-hyper-vectors-building-a-lean-lmu-rwkv-classifier-with-on-the-fly-f8e2ffc03e7c
- author_url
- https://medium.com/@rabmcmenemy
- status
- ok
- fetched_at
- 2026-06-12 07:40:50