Sparse Autoencoders & Dictionary Learning
Decomposing superposition into monosemantic features — from Towards to Scaling Monosemanticity.
- → Explain SAE architecture and the reconstruction–sparsity tradeoff
- → Describe feature splitting and known SAE limitations
- → Train a small SAE and characterize features on Neuronpedia
The problem: you cannot audit a basis you cannot read
Module 3.3 left you with a diagnosis and no cure. Models pack more features than they have dimensions, each feature living along its own direction, all of them interfering slightly. The consequence is that individual neurons are polysemantic: in the one-layer model Anthropic studied, a single neuron fires on academic citations, English dialogue, HTTP requests, and Korean text. Reading the model neuron by neuron is reading it in the wrong basis.
That is not just an aesthetic complaint. If you want to answer “is this model about to deceive the user?” you need a handle on the concept “deception” inside the model. If deception is smeared across four thousand neurons that each also do nine other things, you have no handle.
Why is this solvable at all? Because of sparsity. If a token's activation is a mixture of five features out of a hundred thousand, the mixture is heavily constrained, and — exactly as in compressed sensing — the sparse decomposition is essentially unique. Sparsity is what makes superposition possible and what makes it reversible.
The machine: a deliberately bad autoencoder
A sparse autoencoder (SAE) is the crudest possible approximation to dictionary learning, and it works. Take activations harvested from one site in the model — a residual stream layer, or an MLP's hidden activations. Encode them into a much wider vector, then decode back:
Term by term: is with — the expansion factor is typically 8× to 256×. The ReLU forces every feature activation to be zero or positive, which is what lets you say “this feature is off here.” The columns of are the dictionary: each one is the direction the model writes when that feature fires.
An ordinary autoencoder with a wider middle layer would learn the identity map and tell you nothing. The sparsity penalty is what makes it informative:
The second term is an L1 penalty on feature activations. L1 is a convex stand-in for what you actually want, which is L0 — the raw count of nonzero features — and L0 is not differentiable. Scaling each term by the decoder column norm stops the network from cheating by shrinking activations and growing the corresponding dictionary vector.
Two later variants matter. TopK SAEs (Gao et al., OpenAI, 2024) throw out the L1 penalty and simply keep the largest pre-activations, zeroing the rest. This fixes L0 exactly to , removes the tuning problem, and sidesteps shrinkage — see below. Gated and JumpReLU SAEs (DeepMind, 2024) separate the decision whether a feature is active from the estimate of how active, for the same reason.
What it found: from a toy model to Claude 3 Sonnet
Towards Monosemanticity (Bricken et al., 2023) was the existence proof. One-layer transformer, 512-neuron MLP, sparse autoencoders from 512 up to 131,072 features trained on 8 billion activation samples, with detailed analysis of a 4,096-feature run they call A/1. They found features that are specific in a way no neuron was: an Arabic-script feature that fires on 0.13%-of-corpus Arabic text and accounts for 81% of that text's tokens; base64 features; DNA features. Crucially, the features have causal downstream effects consistent with their interpretation, which is what separates a feature from a correlation.
Scaling Monosemanticity (Templeton et al., 2024) answered the question everyone had: does this survive contact with a real production model? They trained SAEs on the residual stream halfway through Claude 3 Sonnet at three sizes — roughly 1M, 4M and 34M features — using scaling laws to allocate compute. Under 300 features fired per token, and reconstruction explained at least 65% of activation variance.
The features are also abstract in ways that a shallow “this fires on this word” story cannot explain. They are multilingual (the same feature for the same concept across languages), multimodal (text and images), and they bridge concrete and abstract — one feature covers both actual code containing a security vulnerability and English prose discussing security vulnerabilities.
The authors are careful, and you should copy their care: “there's a difference between knowing about lies, being capable of lying, and actually lying in the real world.” The interesting result is not that a deception feature exists — of course it does — but that it can be found at scale and intervened on.
Then they turned the demo into a public one. Clamping the Golden Gate Bridge feature (34M/31164353) to ten times its maximum observed activation produced Golden Gate Claude, a model that steers every conversation toward the bridge and at times identifies itself as the bridge. It ran as a public demo for a day in May 2024. As a party trick it is delightful; as evidence it is the cleanest available demonstration that these dictionary directions are the real causal handles the model uses, not a post-hoc story about correlations. Module 5.1 picks up steering as a technique in its own right.
The honest ledger
SAEs are the most productive idea in interpretability since attention heads, and it is entirely possible they are the wrong abstraction. Hold both.
Two more you should know. Cross-layer superposition: gradient descent does not care which layer a feature lives in, so features get smeared across layers, and an SAE fitted to one layer can only ever see a slice. Anthropic call this “very fundamental” and do not claim to have solved it — it is exactly what the cross-layer transcoders of Module 4.1 are built to attack. Completeness: they do not believe they found anything near all the features in Sonnet, and estimate they may be orders of magnitude short.
Feel it: the frontier and the fragments
Two toys. The first is a working sparse-coding solve on a synthetic activation whose true features you know, so you can catch the SAE being wrong. The second lets you walk a coarse feature down into its fragments as the dictionary widens.
The residual stream at one token: five dense numbers. Every coordinate is nonzero, and no single coordinate means anything on its own — this is superposition.
“…drove across the Golden Gate Bridge before brunch.” Two true features are on. Aqua bars are features that really are present; orange bars are false positives the solver invented to patch the residual.
The solver minimizes with — the same objective an SAE's training loss asks its encoder to approximate — so what you see is the real tradeoff, not a mock-up.
One feature covering everything avian. It fires on sparrows, on roast chicken, on “free as a bird”, and on a paragraph about penguin colonies — all at roughly the same strength.
- …a small brown bird landed on the rail…
- …the bird flu outbreak spread to poultry farms…
- …she felt free as a bird that summer…
Things to try: (1) Drive to 0 on Token D and count the active features — seven light up where only four are real, reconstruction is perfect, and the code is no more readable than the neurons were. That is the failure mode a plain autoencoder has, and it is what the sparsity penalty exists to prevent. (2) Now walk up on Token D: at around 0.9 the weakest true feature dies and reconstruction error passes 60%. Rare, weak features are the first thing sparsity costs you. (3) Switch to Token C and look for the orange bar — the solver reports a Golden Gate Bridge feature that is not there, because that direction happens to patch the residual cheaply. False positives are not a bug in this toy; they are what interference looks like from the inside. (4) Watch the “recovered magnitude” readout as you raise : that is shrinkage, and it is why a feature's activation value is a much less trustworthy number than its identity. (5) In the tree, click ducks, geese & migration and note it has two parents — splitting produces a graph, not a tree, exactly as Bricken et al. report.
Problem set
Do the two pencil problems before the notebook — they are the difference between running an SAE and understanding its output. The Neuronpedia problem is the one to do if you only do one.
Take the simplest possible case: one feature, one dimension, dictionary vector of norm 1. The SAE must choose an activation minimizing
where the true activation is . Solve for the optimal . Then state, in one sentence, what this implies about comparing feature activation values across two SAEs trained with different .
Suppose a residual stream of width carries features, of which on average are active per token. Reconstruction requires the active set to be identifiable from a -dimensional vector.
(a) Argue informally why is the binding constraint rather than . (b) Anthropic's Sonnet SAEs had L0 under 300 with dictionaries up to 34M. Given they also believe they are “orders of magnitude short” of all the features, what does that tell you about the frequency distribution of features?
Go to neuronpedia.org and pick a model with public SAEs — the GPT-2 small residual stream sets, or Gemma Scope on Gemma 2. Search for a concept you actually care about (try something safety-flavored: “refusal”, “flattery”, “lying”, “urgency”) and choose one feature.
Write up half a page covering, in order:
- Your one-sentence hypothesis for what the feature represents, written before you scroll past the top activations.
- Activation distribution. Look at the density histogram and the logarithm of the feature's firing frequency. Is it a common feature or a rare one? Do the top activations look qualitatively different from the ones at 20% of max?
- Specificity check. Find the weakest activations shown. Do they still match your hypothesis? If not, revise it — this is where most naive interpretations die.
- Causal check. Use the feature dashboard's top positive and negative logits, and if the model has a steering interface, steer on it. Does the effect on output match your hypothesis, or only the activations?
In a Colab GPU notebook, use TransformerLens to cache blocks.6.hook_resid_pre activations from GPT-2 small over ~10M tokens of OpenWebText, then train a 16×-expansion SAE (, ) with the loss from the lesson. Normalize decoder columns to unit norm after every step, and resample dead features periodically.
Success check: L0 between 20 and 60, and loss recovered above 80% when you splice the reconstruction back into the forward pass. Then hand-inspect 10 random live features and record how many you can write a one-sentence description for.
Train three SAEs on the same activations at 4×, 16× and 64× expansion, holding L0 roughly constant by tuning per run. Pick a clearly interpretable feature in the 4× run. For every feature in the 64× run, compute the cosine similarity of decoder directions, and separately the correlation of activations over a held-out token set.
Success check: produce a bipartite graph linking the coarse feature to its fine descendants and confirm the two similarity measures broadly agree. Then answer: is the relationship a tree?
Check yourself
Go deeper
Two Anthropic papers carry this module. Read them in order — the 2023 one teaches you the method on a model small enough to fully understand, the 2024 one shows what it buys on a model you actually use.