Glossary
Plain-language definitions of the terms used across this repo — written to teach, not
just define. Each entry gives the idea, the intuition, and (where relevant) the flag or
file it lives in and the FINDINGS.md result it produced. Architecture internals (RoPE,
RMSNorm, SwiGLU) are defined in depth in tech-spec.md; the papers
behind each concept, in learning order, are in
docs/research_roadmap.md; the math is in
docs/math_roadmap.md.
A short version of this file rides along with the site: every page of the
interp lab glosses its own terms in place and
carries the whole list at /glossary,
from web/app/src/data/glossary.json. This file is on the site too, rendered as
/glossary/full — imported
straight out of docs/ at build time, so editing it here updates the page. Those entries are
popover-sized and this file stays the authority for anything it defines; the site adds many terms
this one does not cover (SELFIES, shlyokavitsa, codons, cosine universality, QK-Clip, and more,
growing as new strands ship) — see web/app/src/data/glossary.json for the full set rather than
a hand-maintained list here.
A running thread ties much of this together — the selective-learning campaign (FINDINGS Findings 4–9): a single hypothesis, "the brain updates selectively, so SGD should too," tested five ways. The verdict is a useful lens: selectivity you impose on SGD by hand tends to lose; selectivity SGD arranges for itself tends to win.
1. The model, in one breath
- Decoder-only transformer — the GPT architecture: a stack of identical blocks that reads a sequence of tokens and predicts the next one. "Decoder-only" means it only ever looks left (at past tokens), never right — so it can generate text one token at a time.
- Token — the atomic unit the model reads and predicts. Here, either a character (char-level) or a subword piece (BPE). "Bulgarian" might be one token or several.
- Embedding — a lookup table turning each token id into a vector the model can do math on. The reverse step, vector → token probabilities, is the LM head; weight tying makes those two share one matrix (fewer parameters, usually better).
- Block / layer — one transformer unit = attention + feed-forward, each wrapped in a
norm and a residual.
n_layerof them stacked.n_embdis the vector width,n_headthe number of attention heads. - Attention — the mechanism that lets each token pull in information from earlier tokens, weighted by relevance. SDPA (scaled dot-product attention) is the fast fused implementation. RoPE is how position is encoded (see tech-spec).
- FFN (feed-forward network) — the per-token "thinking" layer after attention. SwiGLU is the modern gated variant used here. Recent work argues FFNs act as key-value memories — they store learned facts/associations.
- Residual / pre-norm — each sub-layer adds its output back to the running stream
(
x = x + sublayer(norm(x))) instead of replacing it, which keeps gradients flowing in deep stacks. Highway residuals add a learned gate deciding how much to add (Finding 2: a real win here, and Finding 16: a win that gets bigger the deeper the stack goes). - block_size — the context length: how many past tokens the model can attend to at once.
2. How a model is trained
- Loss — a number measuring how wrong the model's predictions are; training minimizes it.
- Cross-entropy (CE) — the specific loss for next-token prediction: how surprised the model was by the true next token. Lower = it assigned that token higher probability.
- Validation loss (val loss) — CE measured on held-out text the model didn't train on. The honest score — training loss can be gamed by memorizing. Most tables here rank by val loss.
- bpc (bits per character) — a tokenizer-independent version of loss: bits needed to
encode each character. Lets you compare models with different tokenizers fairly
(
experiments/bulgarian/bpc_eval.py). Lower = better. - Perplexity — cross-entropy exponentiated, so it reads as "how many equally-likely
tokens was the model choosing between here?" A perplexity of 10 means it was about as
unsure as someone picking uniformly from 10 options. It is what
score.pyreports, and the basis of the fluency-judge use: compare two candidate sentences and the lower-perplexity one is the more natural Bulgarian. Only comparable within one model and tokenizer. - nats — the unit loss is measured in here (natural-log cross-entropy; bpc is the same quantity in base-2 bits). A margin of "0.03 nats" between two models is a small but real difference in how well they predict the next token. Lower = better.
- Gradient — the direction and size of the nudge to each weight that would most reduce the loss, computed by backpropagation (backprop). Training = repeatedly nudging weights along the negative gradient.
- SGD (stochastic gradient descent) — the base training loop: on each mini-batch, compute the gradient and step the weights against it. "Stochastic" = uses a random batch, not the whole dataset, each step.
- Momentum — instead of stepping on the raw gradient, keep a running average of recent gradients and step on that. Smooths noise, accelerates through consistent directions.
- AdamW — the default optimizer here and almost everywhere: adds per-parameter adaptive step sizes (each weight scaled by its own recent gradient magnitude) plus decoupled weight decay. The "implicit selectivity" many of our experiments kept losing to — Adam already gives settled weights small steps and noisy ones large ones.
- Learning rate (LR) — how big each step is. Too high diverges, too low crawls. The single most important knob. Warmup ramps it up early; cosine decay ramps it down late — both standard, both used here.
- Batch / mini-batch — the group of examples processed together per step. Epoch = one full pass over the dataset.
- Scaling law — an empirical rule for how loss falls as you grow model size, data, or compute (usually a power law). The famous ones (Kaplan 2020, Chinchilla) are fit with a fixed optimizer/architecture; Finding 15 is a case where a training trick bends the curve non-uniformly, on an architectural axis (head size) those laws collapse away.
- Chinchilla-optimal — the compute-efficient ratio of training tokens to parameters (~20 tokens per parameter). Training much past or short of it wastes compute. Guides how long the flagship runs go. "Sub-Chinchilla" (Finding 15) = models smaller than the smallest in the Chinchilla study (~70M).
3. The optimizer axis (Findings 8–9)
- Muon (MomentUm Orthogonalized by Newton-schulz) — a recent optimizer (Jordan et al.
2024) that beat AdamW here at parameter parity (Finding 9). It's SGD-momentum with one
extra step: before each update it orthogonalizes the update matrix.
--optimizer muon,gpt_alpha/optim.py. - Orthogonalization — replacing a matrix with the "most orthogonal" matrix near it, i.e. forcing all its singular values to ≈1. Intuition: a raw gradient update is low-rank — a few directions dominate and eat the whole step, so most of a weight matrix barely moves. Orthogonalizing equalizes the update so every direction learns at once. That's why Muon helps: it uses the whole matrix's capacity each step.
- Singular values — the "stretch factors" of a matrix along its principal directions (from the SVD). Forcing them to 1 = pure rotation, no stretching = orthogonal.
- Newton-Schulz iteration — the cheap trick to orthogonalize without an SVD (which is
slow on GPUs): ~5 rounds of a matrix-multiply-only polynomial that pushes the singular
values toward 1.
zeropower_via_newtonschulz5inoptim.py. - meProp (minimal-effort backprop, Sun et al. 2017) — keep only the top-k% of each
gradient by magnitude, zero the rest, so each step updates only the most-active weights.
Our purest test of "selective updating" — and it hurt, dose-dependently (Finding 8).
--grad-topk,sparsify_grads_intraining.py.
4. Mixture of Experts (Findings 5–7)
- MoE (mixture of experts) — replace the single FFN with several smaller "expert" FFNs
plus a router that sends each token to one (or a few) of them. Only the chosen experts
run, so you can add parameters without adding per-token compute.
--ffn moe. - Expert — one of the parallel FFN sub-networks. A token is processed by whichever expert(s) the router picks.
- Router — a small learned layer that scores each token against every expert and picks
the top ones. Routing by learned token affinity is standard; we also tried routing by
competence (
--router-progress, Finding 5 — it hurt). - Top-k routing — send each token to its top-k experts (k=1 is Switch-style; k=2+ is GShard/Mixtral-style). The chosen experts' outputs are combined, weighted by the router's scores.
- Load-balancing aux(iliary) loss — an extra training-time penalty that discourages the router from dumping every token on one expert (expert collapse), keeping the experts evenly used. Off at eval, so val loss stays pure CE.
- Granularity — how finely the FFN is split: few big experts vs many small ones. The literature says finer helps at scale; here it was a null (Finding 7: 16 small experts ≈ 4 big ones).
- Active vs total parameters — total = all experts' weights; active = only those a given token actually runs through. MoE's trick is high total, low active. Conditional compute is the general name for "different inputs use different parts of the network."
- Parameter parity (param-matched) — comparing two models with the same total parameter count, so any difference is the mechanism, not just "more weights." The discipline behind Findings 6–7: a param-matched MoE ties or loses to a dense model here; MoE's apparent win was capacity (2× the parameters), not the mechanism.
5. Training signals and selectivity (Findings 4–6)
- Learning-progress weighting — upweight tokens whose loss is currently falling (the
"learning frontier"), downweight both mastered tokens (flat-low loss) and unlearnable ones
(flat-high loss). The developmental-learning idea; tested via
--progress(Finding 4 — it hurt). Contrast artificial curiosity (Schmidhuber), which upweights raw high loss (surprise) and conflates the frontier with noise (--curiosity, also a null). - EMA (exponential moving average) — a running average that weights recent values more. A fast EMA (short memory) minus a slow EMA (long memory) estimates a trend — how fast something is changing. Used to estimate per-token learning progress and per-expert competence.
- Competence routing — bias an MoE router toward experts whose tokens are currently improving (a fast/slow-EMA competence signal). The "brain routes to circuits that have learned this" idea (Finding 5 — it hurt: the bias could only shift bulk load, and it oscillated).
- Selective updating — the campaign's umbrella idea: rewrite only part of the network each step, like biological consolidation, rather than nudging every weight. Tested at the loss (F4), the routing (F5), the MoE write (F6), and the optimizer (F8). All lost — because SGD/Adam already does a good implicit version.
- Spectral bias / implicit curriculum — the well-documented fact that SGD naturally learns simple, low-frequency, high-frequency-of-occurrence patterns first, before complex ones — an easy-to-hard curriculum for free. This is why our hand-imposed curricula kept losing: they fought a curriculum SGD already runs.
6. How we decide what's real (methodology)
- Ablation — remove or swap one component and measure the effect, holding everything else
fixed.
ablate.pyruns configs × seeds under identical settings. - Seed — the random-number starting point (weight init, batch order). Different seeds = slightly different runs. We train 3 seeds per config and report the seed range; a difference counts as real only if the two configs' seed ranges don't overlap — the repo's bar for significance.
- Null result — a measured "no effect": the change lands inside the baseline's seed
spread. House rule: nulls are documented, not deleted — they're most of
FINDINGS.md. - Param-matched control — a comparison arm with equal parameters, to tell a mechanism win from a capacity win (more weights). Without it, "bigger helped" masquerades as "idea helped." See parameter parity above.
- Capacity confound — when a result could be explained by "it just had more parameters." The thing param-matched controls exist to rule out.
- Dose–response — vary the strength of an intervention and check the effect scales monotonically. meProp showed a clean one (more sparsity → worse, Finding 8), which makes the negative result credible.
- Double dissociation — the gold-standard evidence for two separate functions: find one manipulation that breaks A but not B, and another that breaks B but not A. The proposed shape for a syntax-vs-semantics ("Broca/Wernicke") localization study.
- Scale trend — measure the same effect at several model sizes to see whether it grows, holds, or shrinks with scale. Small-scale wins that grow are the ones worth scaling up. The Muon scale-trend (3.4M → 15M → 33M) is exactly this.
- Replication vs discovery — reproducing a known result (e.g. Muon beats AdamW) validates a lever for this project but is not new knowledge for the field. The honest framing of Finding 9: a useful, adoptable replication, not a discovery.
- No re-running verified experiments — a project convention: compare new arms
against numbers already in
FINDINGS.mdrather than re-measuring them, unless the settings changed (and then say so). Compute goes to gaps, not confirmations. - Zero-shot evaluation — scoring a model on a task it was never trained for and given no
examples of. For multiple-choice questions a base LM can still be scored without any
fine-tuning: put each answer after the question and pick whichever the model finds most
likely (
experiments/bulgarian/bg_zeroshot.py). acc_norm is the same thing with each answer's score divided by its length, which stops short answers from winning by default. - Chance baseline — what a model scoring at random would get (25% on a 4-choice task). A benchmark number is only evidence of knowledge if it clears chance by more than its own standard error; for 1000-odd questions that error is about ±1.2 points, so 27% is not a result. Reporting the error bar next to the score is what makes the difference visible.
- Quantization — storing weights in fewer bits (here int8: one byte instead of four),
which shrinks a model roughly 4× for deployment. The question is always what accuracy it
costs; QAT (quantization-aware training) is the extra training stage that teaches a
model to tolerate the rounding. Measured on
ckpt_bg15m, plain int8 costs +0.0018 bpc, so QAT was skipped and the null recorded (export_onnx.py).
7. Interpretability terms (Phase 9)
- SAE (sparse autoencoder) — a probe trained to re-express a layer's activations as a
sparse combination of many learned features, each ideally standing for one
human-legible concept (e.g. "definite article, masculine"). The repo's microscope for
what the Bulgarian model represents (
experiments/interpretability/bg_sae.py). - Feature — one direction/unit an SAE learns; the hoped-for atom of "what the model knows."
- Steering — clamping or amplifying a feature during generation to test whether it causes a behavior (correlation → causation).
- Trace — a recorded snapshot of the model's internals on one input (attention weights, residual stream, logits), rendered by the interpretability viewers. Verified bit-identical to the untraced forward pass.
- Logit lens — reading out what the model "would predict" from an intermediate layer, to watch a prediction form across depth.
- Probe / d′ (d-prime) — a small classifier (or a separation score) testing whether some information is linearly present in the activations. d′ measures how cleanly two conditions separate.
- Attention sink — a head that puts nearly all its attention on the first token. Softmax
makes every attention row sum to 1, so a head with nothing it wants to look at still has to
put its weight somewhere, and the first position is the usual dumping ground. The sink is
a way of doing nothing. It matters because it is the loudest thing in most traces, so any
procedure that ranks heads by attention weight will surface sinks before it surfaces
mechanisms — which is exactly how this repo's own viewer once labelled a sink row as an
induction head (
findings/interpretability/interp_FINDINGS.md, Finding 4). The lesson generalizes past that bug: salience is not evidence. To claim a head does something, score that something directly — for induction, the strict-bigram criterion inexperiments/interpretability/pair_stats.py. - Phase change — a capability that arrives abruptly during training rather than improving
smoothly: flat for a long stretch, then a jump, then a plateau. The name is borrowed from
physics, where water cooled steadily through 0°C does not get steadily more solid — the input
changes smoothly and the output does not. Induction heads are the best-known example (Olsson
et al. 2022), and this repo measures one directly: on Pythia-160M the best head's induction
score sits at 0.016–0.019 for 512 training steps, hits 0.9803 by step 1000, and then holds
that level for the remaining 142,000
(
findings/interpretability/induction_onset_FINDINGS.md). Two consequences worth carrying around. The loss curve stays smooth through it, so nothing in the training log tells you a mechanism just appeared — you have to measure the mechanism. And averages over training hide it: a comparison of final checkpoints cannot see a phase change at all, so if you want to know whether some intervention moved when a circuit forms, the checkpoints have to be dense around the onset or the whole event falls between two saves.
8. The attention axis (Findings 17–18)
Softmax attention is not the only way a model can look back at what it has already read. This repo carries a second family, and the terms below are what the 2026-07-28 findings turn on.
- Fast weights — Schmidhuber's 1992 alternative to attention, revived as "linear
attention." Instead of comparing the current token against every earlier one (what softmax
does, at O(T²) cost), the model keeps a single memory matrix and writes each token into
it as it goes, then reads the memory to produce output. Attention re-reads the whole past;
fast weights carry a running summary of it.
--attn linear|delta|gated-delta. - Delta rule — the write rule that makes fast weights competitive. Rather than blindly adding each new token to the memory, the model first reads what it already believes about that key, and writes only the difference — the surprise. Old information is corrected rather than piled on top of. This is the classic error-correcting update (Widrow–Hoff, 1960), used as a memory write.
- Decay gate (Gated DeltaNet / Kimi Delta Attention) — a learned "forget" control on the memory: before each write, the existing memory is multiplied by a value between 0 and 1, so old contents fade unless refreshed. Without it the memory only ever accumulates. Two published granularities exist: Gated DeltaNet emits one decay value per head (a scalar, inherited from Mamba2), and Kimi Delta Attention refines that to one per channel, so each feature dimension forgets at its own rate. Finding 19 runs both: the per-head form matches the per-channel one at 1/32 the gate parameters, so the gain is the mechanism rather than the extra capacity it came wrapped in, and the finer gate does not pay for itself at this scale and context length. The null is against the refinement, not against gating, and it agrees with Gated DeltaNet's own choice.
- Positional encoding, and NoPE — a transformer has no inherent sense of order, so
position is normally supplied: learned embeddings (one vector per slot) or RoPE (a
rotation whose angle grows with position; see
tech-spec.md). NoPE (Kazemnejad et al. 2023) supplies none at all and lets a causal model infer order from the structure of the computation itself.--pos rope|learned|none|alibi|hard-alibi. - The positional confound — the methodological lesson, and the one worth carrying to any new comparison. Fast-weight configs here use learned positions because RoPE was assumed not to apply to them, so for a long time every fast-weight-vs-softmax comparison in this repo silently changed two things at once. It biased the answer in both directions: it flattered delta in the length-generalization study and penalized it by 0.176 in the write-gate study, which stood in flat contradiction to a third document reporting a tie. Finding 17 priced the positional axis at 0.180 and resolved all three. When two architectures cannot share a setting, that setting is part of the experiment, not part of the background.
- Interference vs redundancy — Finding 18's result, and a distinction worth keeping. Softmax needs positional encoding; plain delta is indifferent to it; a gated fast-weight arm is harmed by it. The decay gate already encodes recency, so adding position does not merely duplicate the job — it actively gets in the way. Two mechanisms doing the same work can be worse than either alone, which is why the composability of two winners is something to measure rather than assume.