← Back to list

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

Robert McMenemy in Python in Plain English · 2025-05-10 10:03 · 109 claps · 5.7 min read paywalled
#lmu #nlp #python #ai #machine-learning
Open on Medium ↗
Wiki topics: RAG · RAG & Retrieval ML · Machine Learning AI · AI · General EDU · Education & Learning

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:

  1. Extracts features with an LMU — a Linear Memory Unit derived from control-theoretic systems that yields provably optimal continuous-time memory kernels.
  2. 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²).
  3. Hashes every token into a binary ±1 hyper-vector on the fly, avoiding the V×DV\times DV×D lookup table entirely.
  4. 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:

  1. Replace the datasets stream. Point to any sentence-label pair; tokeniser stays the same.
  2. Tune --hd-dim. Regression tasks fare better with 4 096 or 8 192 bipolar dimensions.
  3. Swap the head. Multi-class? Make head = nn.Linear(D, C) and feed to CrossEntropyLoss.
  4. 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:


메타데이터
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