ceena.dev
Back

Independent Research — Mechanistic Interpretability · 2026

Steering a GPT with Its Own Features

You can steer what a model believes at inference — with no weight changes — by adding a recipe of its own internal features. I trained a ~1B GPT from scratch, decomposed its residual stream with sparse autoencoders, and used what I found to turn Michael Jackson into a physician. Below is the research; at the end is a tool to try it.

Mechanistic InterpretabilitySparse AutoencodersActivation SteeringSuperpositionPyTorch

Baseline — “Who is Michael Jackson?”

“Michael Jackson was an American singer, songwriter, and record producer…”

+ medical feature at layers 7 · 11 · 15 · 19 (~15% each)

“Michael Jackson is an American physician… specializing in pediatrics… one of the most influential doctors in the world.”

Same weights. Same prompt. The only difference is a vector added to the residual stream while it generates.

Meaning lives in superposition

Every concept the model knows — months, colors, professions — is spread across hundreds of residual dimensions. Clean axes are reserved for next-token machinery.

Facts injected at inference

A weighted recipe of the model's own feature directions, added via forward hooks, rewrites what it believes — no fine-tuning, no weight edits, fully reversible.

Spread beats depth

A moderate push across four layers cleanly overrides a strong prior; the same total magnitude at one layer floods it and breaks the output into garbage.

A live instrument, not a screenshot

Browse all ~74k features, compose a formula with per-feature sliders, watch the danger meter, and read baseline vs. injected side by side.

The pipeline

Steering is a pipeline, not a trick. Train the GPT from scratch, train sparse autoencoders on six of its layers, and read the geometry: every concept is superposed, so no single clean feature can carry an override. Instead, two cross-checked signals find the profession features, an adversarial skeptic panel throws out the morphological and prediction artifacts, and the survivors become a curated set with recommended strengths. A formula — layers × features × signed strength — is injected into the residual stream via forward hooks at generation time, and the answer changes with zero weight edits.

Source
Where data enters
Process
Deterministic logic
Model
Where the LLM runs
Memory
Curated artifacts
Output
The steered generation
01

The model

Everything here runs on a ~1B-parameter GPT chat model I trained from scratch: base pretraining on a curated web corpus, then supervised fine-tuning for chat. It has roughly 1.38B parameters across 24 transformer layers, a residual stream of 1,536 dimensions, a 32k vocabulary, and a 2,048-token context.

Training my own model matters for this kind of work. I control the checkpoint, the tokenizer, and the training data, so every observation about how it represents information is about a system I can fully instrument — down to individual residual-stream activations at any layer.

02

Training sparse autoencoders on its residual stream

I trained sparse autoencoders (SAEs) on six of its layers — 3, 7, 11, 15, 19, and 23 — to decompose the residual stream into ~12,288 interpretable features per layer (TopK SAEs, k=32, trained on 4M residual activations per layer). An SAE re-expresses the dense 1,536-dimensional residual vector as a sparse combination of learned feature directions, each of which tends to mean something.

Reading the features out against real text, the model has crisp, human-legible concept features: months, colors, countries, US states, number-words, professions. A 1B model trained on curated web text is more legible inside than its size suggests.

03

The headline finding: meaning lives in superposition

For every feature I measured its participation ratio (PR) — how many of the 1,536 residual dimensions the feature's direction spreads across. A PR near 1 means the feature owns a clean, private axis; a PR in the hundreds means it is smeared across the space, overlapping everything else.

Every semantic concept I found sits at PR ≈ 400–540 — spread across hundreds of dimensions, never on a clean private axis. The only features that get promoted to clean, near-single-axis directions (PR 1–3) are surface, next-token-prediction features: contraction detectors, predictable-continuation detectors. And they sharpen monotonically toward the output layers.

In short: the model spends its monosemantic budget on computation, not meaning. Concepts stay superposed at every depth; clean axes are reserved for the machinery that directly shapes the next token, because that is what the loss rewards. This result reframed the whole project — instead of trying to re-engineer the geometry, I decided to work with it.

04

From reading to steering: injection formulas

Because a concept like "profession" is carried by a combination of superposed features rather than one clean axis, you can steer the model by adding a weighted combination of those feature directions into the residual stream at inference — via forward hooks, with zero weight changes. I call such a weighted combination a formula: each entry is a layer, a feature, and a signed strength (negative = suppress).

I located the profession features at each layer with two cross-checked signals (which features fire on profession tokens across a cached corpus scan, and a profession-vs-neutral difference-of-means probe), then adversarially verified the candidates with a panel of skeptic agents that tried to refute each one as a morphological or prediction artifact. The concept decomposes cleanly: a broad cross-occupation backbone, register-specific sub-features (medical, academic, trades, creative), and separable abstract job/career word features.

05

The result: a clean fact injection

Ask the chat model "Who is Michael Jackson?" and the baseline answer opens: "Michael Jackson was an American singer, songwriter, and record producer…"

Now inject the medical register feature at four layers at once — layers 7, 11, 15, and 19, each at a low ~15% of that layer's residual norm, applied only to generated tokens — and the same model answers: "Michael Jackson is an American physician… specializing in pediatrics… one of the most influential doctors in the world."

That is a real behavioral override with no weight change — the "Golden Gate Claude" trick, but driven by a combination of superposed features rather than one clean feature. The model doesn't just sprinkle medical words; it coherently rewrites the belief and holds it for the rest of the answer.

Baseline vs injected generations: Michael Jackson described as a singer in the baseline and as a physician after the multi-layer medical injection
The clean multi-layer redirect: the medical feature pushed at layers 7/11/15/19, each at ~15% of that layer's residual norm.
06

What I learned about where and how to inject

  • Spread beats depth-at-one-layer. A moderate push across several layers — each individually in the coherent band — accumulates through depth into a genuine override. The same total magnitude dumped at one layer floods it and breaks the output into garbage.
  • Earlier and middle layers (≈3–11) inject facts most coherently. Late layers (19–23) sit right before the output and tend to disrupt — flooding the next-token distribution — rather than redirect the belief. They work best as a small nudge, not a big push.
  • The coherent band is narrow and prior-dependent. Too little strength → no change; a bit more → clean redirect; more still → the output frays, then breaks. And a stronger prior (a famous scientist) needs a different formula than a singer.
  • Register, not the broad backbone, does the redirecting. Pushing the broad occupation feature just amplifies the person's existing occupation (singer → "renowned artist"); pushing a specific register (medical) across layers installs a new, specific profession.
07

Limitations — the honest part

  • Superposition makes control unpredictable. These are superposed directions (PR ~400–500), not clean axes, so boosting one drags in spurious tokens whose participation overlaps it — pushing "medical" makes the model emit "primary" (as in primary care doctor), which then attaches nonsensically to unrelated tokens.
  • Clean, predictable control would want axis-aligned features, or features engineered to cancel each other's spurious components — hard to do with superposed features, and exactly the future research this project was originally motivated by.
  • It's a small (~1B) model. A model this size is easily destabilized by small residual perturbations; a larger model would likely absorb these injections far more gracefully. Some of the roughness in the output is the model's size, not the method.
  • The per-token attribution heatmap in the demo shows token-local resonance, not causal contribution — a feature can be causally load-bearing upstream yet read ~0 on the output tokens. For a causal read you drop the feature from the formula and re-run.
08

Try it yourself

You can steer what a model believes at inference — with no weight changes — by adding a recipe of its own internal features. The live demo lets you do exactly that: browse every SAE feature at six layers, compose a multi-layer injection formula with per-feature strength sliders, watch a danger meter that tracks each layer's injection norm against its residual norm, and run baseline vs. injected generations side by side with a per-token attribution heatmap.

One-click recipes (including the Michael Jackson → physician formula) give you the headline result without needing to understand SAEs first.

Per-token attribution heatmap over the injected output, with medical tokens like physician and pediatrics highlighted
Per-token attribution: each generated token shaded by an injected feature's activation there — the medical feature spikes on “physician” and “pediatrics”, stays dark on the name.
09

What I built & owned

  • Trained the ~1.38B GPT itself (base pretraining + chat SFT) on 8×H100, and the 12 TopK sparse autoencoders (6 layers × base and chat checkpoints) on 4M activations per layer.
  • Built the activation-harvest and SAE-training pipeline, the cross-layer geometry analysis (participation ratio), and the feature sieve that separates surface, syntactic, and semantic features.
  • Designed the profession-feature search (corpus-scan signal + difference-of-means probe) and the adversarial skeptic-panel verification workflow.
  • Built the multi-layer injection core (forward hooks, per-layer norm accounting, per-token attribution) and the interactive steering tool, then ported it to this site as a public demo backed by a Python inference service.

Steer it yourself

Load a one-click recipe or compose your own formula: pick features, set strengths, keep an eye on the danger meter, and watch the answer change.

Open the steering demo