---
abstract: Reverse engineering the representations and computations inside neural networks, then testing those explanations through interventions.
aliases:
  - mechinterp
  - reveng neural net
  - interp
date: '2024-10-30'
description: Features, circuits, and causal tests for reverse engineering neural networks.
id: mechanistic interpretability
layout: technical
modified: 2026-10-23 02:16:18 GMT-04:00
permalinks:
  - /mechinterp
  - /interpretability
seealso:
  - '[[thoughts/sparse autoencoder|sparse autoencoder]]'
  - '[[thoughts/sparse crosscoders|sparse crosscoders]]'
  - '[[thoughts/Attribution parameter decomposition|Attribution parameter decomposition]]'
socials:
  glossary: https://dynalist.io/d/n2ZWtnoYHrU1s4vnFSAQ519J
  tour: https://www.youtube.com/watch?v=veT2VI4vHyU&ab_channel=FAR%E2%80%A4AI
tags:
  - ml
  - alignment
  - llm
  - interp
title: mechanistic interpretability
created: '2024-10-30'
published: '2024-10-30'
pageLayout: technical
slug: thoughts/mechanistic-interpretability
permalink: https://aarnphm.xyz/thoughts/mechanistic-interpretability.md
generator:
  quartz: v4.6.0
  hostedProvider: Cloudflare
  baseUrl: aarnphm.xyz
full: https://aarnphm.xyz/llms-full.txt
---
mechanistic interpretability asks how a neural network produces a behaviour. An explanation identifies representations and computations inside the network, then predicts what will happen when we change them. Alignment supplies many of the motivating questions, especially for [[thoughts/LLMs|LLMs]].

The scale problem remains: _<mark>how do we hope to understand a function over such a large space, without an exponential amount of time?</mark>_ [^lesswrongarc] Decomposition is one proposed answer. If the same components recur across inputs, we can study their interactions and reuse that explanation. We still have to establish where it holds.

[^lesswrongarc]: [Lawrence C’s ambitious mechanistic interpretability agenda](https://www.lesswrong.com/posts/6FkWnktH3mjMAxdRT/what-i-would-do-if-i-wasn-t-at-arc-evals#Ambitious_mechanistic_interpretability).

## open problems

see also: [Neuronpedia’s August 2025 landscape](https://www.neuronpedia.org/graph/info#section-directions-for-future-work), @sharkey2025openproblemsmechanisticinterpretability

Finding a direction associated with a concept gives us a hypothesis about representation. Reverse engineering also requires an account of how the model uses it. The working sequence is decomposition, hypotheses, and intervention tests.

- **Choosing components.** [[thoughts/university/twenty-four-twenty-five/sfwr-4ml3/principal component analysis|PCA]] finds directions of variance. [[thoughts/sparse autoencoder#sparse dictionary learning|Sparse dictionary learning]] finds directions that reconstruct activations with sparse coefficients. Each objective imposes a different decomposition; neither objective establishes a component’s causal role.
- **Reconstruction.** Sparse autoencoders trade reconstruction fidelity against sparsity. Gated SAEs improve this tradeoff in their experiments by separating feature selection from magnitude estimation. The remaining error needs to be measured at the activation and model-output levels. \[@rajamanoharan2024improvingdictionarylearninggated\]
- **Representation assumptions.** A linear decoder assumes that activations can be approximated by sums of feature directions. Curved or context-dependent representations can require many such directions.
- **Geometry.** A dictionary can identify useful directions while leaving their relationships unexplained. What determines their angles, groups, and dependence on context? ^geometry

![[thoughts/circuit tracing#limits]]

## transcoders

An SAE reconstructs the activations it receives. A transcoder receives a component’s input and predicts its output, commonly the output of an MLP. @paulo2025transcodersbeatsparseautoencoders reports more interpretable features in the tested setting. Their skip transcoder adds an affine input-to-output path and improves reconstruction at comparable interpretability.

A cross-layer transcoder, or CLT, extends this across layers. A feature read at layer $\ell$ contributes to reconstructed MLP outputs at layers $\ell,\ell+1,\ldots,L$. Including its own layer matters. See [[thoughts/circuit tracing#the replacement model|the replacement-model equations]] and the [CLT architecture](https://transformer-circuits.pub/2025/attribution-graphs/methods.html).

## inference

Projects to follow: [Goodfire](https://goodfire.ai/) and [Transluce](https://transluce.org/).

> \[!question\]- How would we do inference with an SAE?
>
> <article class="twitter-post" data-twitter-source="https://x.com/aarnphm/status/1839016131321016380"><span class="twitter-post-badge" role="img" aria-label="Twitter post" title="Twitter post"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="64 64 896 896" fill="currentColor" stroke="none" stroke-width="0" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M928 254.3c-30.6 13.2-63.9 22.7-98.2 26.4a170.1 170.1 0 0075-94 336.64 336.64 0 01-108.2 41.2A170.1 170.1 0 00672 174c-94.5 0-170.5 76.6-170.5 170.6 0 13.2 1.6 26.4 4.2 39.1-141.5-7.4-267.7-75-351.6-178.5a169.32 169.32 0 00-23.2 86.1c0 59.2 30.1 111.4 76 142.1a172 172 0 01-77.1-21.7v2.1c0 82.9 58.6 151.6 136.7 167.4a180.6 180.6 0 01-44.9 5.8c-11.1 0-21.6-1.1-32.2-2.6C211 652 273.9 701.1 348.8 702.7c-58.6 45.9-132 72.9-211.7 72.9-14.3 0-27.5-.5-41.2-2.1C171.5 822 261.2 850 357.8 850 671.4 850 843 590.2 843 364.7c0-7.4 0-14.8-.5-22.2 33.2-24.3 62.3-54.4 85.5-88.2z"></path></svg></span><header class="twitter-post-header"><span class="twitter-post-author">@aarnphm</span><time datetime="2024-09-25">2024-09-25</time><a class="twitter-post-source" href="https://x.com/aarnphm/status/1839016131321016380" target="_blank" rel="noopener noreferrer" aria-label="Open original post (opens in a new tab)" title="Open original post" data-skip-icons="true"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M7 17 17 7M7 7h10v10"></path></svg></a></header><div class="twitter-post-body">
> 			
> 				
> 					<p>Quick 🧵 and some of quick introspection into how they might run inference</p>
> 				
> 			
> 			
> 		<blockquote><cite><a href="https://x.com/GoodfireAI/status/1839002465984741745" target="_blank" rel="noopener noreferrer" data-skip-icons="true">@GoodfireAI</a></cite>
> 			
> 				
> 					<p>Today, we’re releasing our research preview (<a href="https://t.co/Ssnaxg1zZW" target="_blank" rel="noopener noreferrer">https://t.co/Ssnaxg1zZW</a>) to let you look inside your AI.</p>
> <p>We've created a desktop interface that helps you understand and control Llama 3's behavior. You can 1) see Llama 3's internal features (the internal building blocks of its responses) and 2) precisely adjust these features to create new Llama variants.</p>
> <p>Try it out and share your findings with #GoodfireAI</p>
> 				
> 			
> 			
> 		<video src="https://video.twimg.com/ext_tw_video/1838982966732611585/pu/vid/avc1/1280x720/MqQOGqocd4UaldGC.mp4?tag=12" controls preload="none" playsinline poster="https://pbs.twimg.com/ext_tw_video_thumb/1838982966732611585/pu/img/xThhXaRy7PYl_GWF.jpg"></video></blockquote></div></article>

idea: expose feature controls during generation. A logit bias changes scores for vocabulary tokens at the output. An SAE intervention changes an internal activation, after which the remaining network computes new logits. That distinction determines where an inference engine needs a hook. [[thoughts/structured outputs|Structured output constraints]] operate at the token-selection boundary and can enforce a grammar; an internal steering vector supplies no equivalent guarantee.

> \[!abstract\] proposal for a <ref slug="thoughts/vllm"> plugin
>
> Design targets: less than $5\%$ latency overhead, support for CLTs and matryoshka SAEs, feature drift detection, and measurements of latency and intervention effects. These are requirements to test, with overhead measured against the same workload without the plugin.

see also: [[hinterland/attn/interp plugins|proposal for efficient SAE plugin support]]. The intervention interface depends on the representation: a CLT feature has decoder vectors for several layers, while a single-site SAE feature has one decoder direction at its training site.

## steering

Steering changes a model’s activations during a forward pass. For an activation $h_{\ell,t}$ at layer $\ell$ and token position $t$, an additive intervention is

$$
h'_{\ell,t}=h_{\ell,t}+\alpha d_i.
$$

Here $d_i$ is a chosen direction, such as decoder feature $i$ from a [[thoughts/sparse autoencoder|sparse autoencoder]], and $\alpha$ sets the strength. The feature index and the strength are separate choices. [^1]

[^1]: Some implementations set $\alpha=s m_i$, where $m_i$ is a reference activation magnitude for feature $i$ and $s$ is a dimensionless multiplier. State the reference dataset and statistic when using this convention. A recorded maximum depends on which examples were sampled.

For the prompt “The weather in California is”, the unmodified computation might favour “hot”. An intervention could change that distribution:



```pele
---
config:
  flowchart:
    nodeSpacing: 20
    rankSpacing: 28
    curve: step
---
swimlane-beta LR
  subgraph baseline["unmodified pass"]
    prompt["<b>prompt:</b> <i>The</i><br/><i>weather in</i><br/><i>California is</i>"]
    early@{ shape: st-rect, label: "<b>layers through</b><br/>$$1\ldots\ell$$" }
    clean(["<b>chosen state</b><br/>$$h_{\ell,t}\text{ at }(\ell,t)$$"])
    late_b@{ shape: st-rect, label: "<b>later layers</b><br/>$$\ell+1\ldots L$$" }
    out_b["<b>next-token probabilities</b><br/>$$P(y\mid x)$$<br/>favours “hot”"]
  end

  subgraph steered["steered pass"]
    hook@{ shape: subproc, label: "<b>edited state</b><br/>$$h'_{\ell,t}=h_{\ell,t}+\alpha d_i$$" }
    late_s@{ shape: st-rect, label: "<b>later layers</b><br/>$$\ell+1\ldots L$$" }
    out_s["<b>next-token</b><br/>$$P(y\mid x;\alpha d_i)$$<br/>test “cold”"]
  end

  subgraph vector["steering vector"]
    sae["<b>SAE decoder</b><br/>feature dir $$d_i$$"]
    caa["<b>CAA vector</b><br/>$$\mathbb{E}[a(c_p)-a(c_n)]$$"]
    scale@{ shape: hex, label: "<b>strength</b><br/>$$\alpha$$<br/>offset $$\alpha d_i$$" }
  end

  prompt --> early
  early --> clean --> late_b --> out_b
  clean -->|$$h_{\ell,t}$$| hook
  sae --> scale
  caa --> scale
  scale -.->|$$+\alpha d_i$$| hook
  hook ==> late_s ==> out_s
```

“Cold” becoming more likely would be an experimental result to measure. Naming the direction “cold” does not establish that effect, and large edits can disrupt unrelated behaviour. [[thoughts/mechanistic interpretability#ablation|Ablation]] tests what happens when a component’s contribution is removed or replaced.

### [[thoughts/contrastive representation learning|contrastive]] activation additions

Contrastive activation addition (CAA) constructs a direction from paired examples. In @panickssery2024steeringllama2contrastive, each pair shares a multiple-choice question and differs in its final answer letter. One answer expresses the target behaviour. Activations are read at the answer-letter position.

For triples $(p,c_p,c_n)\in\mathcal{D}$, define

$$
v_{\mathrm{MD}}^{(L)}
=\frac{1}{|\mathcal{D}|}
\sum_{(p,c_p,c_n)\in\mathcal{D}}
\left[a_L(p,c_p)-a_L(p,c_n)\right].
$$

The subtraction belongs inside the sum. Pairing reduces variation from the question’s wording; averaging combines the remaining differences. This mean-difference estimator uses the behaviour labels. PCA instead selects directions by variance.

At inference, the paper adds $\alpha v_{\mathrm{MD}}^{(L)}$ at post-prompt token positions. See the [method and experiments](https://aclanthology.org/2024.acl-long.828/) and [code](https://github.com/nrimsky/CAA).

> \[!tip\] scope of the result
>
> On the paper’s Llama 2 sycophancy experiment, CAA transferred from multiple-choice examples to open-ended generation where the tested finetuning setup failed. This supports transfer in that setting. A general advantage over supervised finetuning remains a separate claim.

## superposition hypothesis

A linear representation uses superposition when its feature directions are linearly dependent. In the common overcomplete case, there are more feature directions than dimensions. Sparse features make this useful because only a few are active on a given input, reducing interference between them. @elhage2022superposition demonstrates this in small networks with synthetic features; the [toy notebook](https://colab.research.google.com/github/anthropics/toy-models-of-superposition/blob/main/toy_models.ipynb) makes the assumptions inspectable.

Suppose a model represents feature strengths $x_i$ using directions $w_i$:

$$
h=Wx=\sum_{i=1}^{m}x_iw_i,
\qquad W\in\mathbb{R}^{d\times m}.
$$

For unit-length directions, reading along $w_j$ gives

$$
w_j^\top h=x_j+\sum_{i\ne j}x_i w_j^\top w_i.
$$

The second term is interference. Sparsity sets many of its coefficients to zero; small pairwise inner products reduce the remaining terms. Nonlinear filtering can then help recover features. This explains how superposition can act as **lossy [[thoughts/Compression|compression]]**.

High-dimensional geometry permits many directions with small pairwise inner products. The number depends on the tolerated overlap and the dimension; see the [[thoughts/Johnson-Lindenstrauss lemma|Johnson-Lindenstrauss lemma]]. Compressed sensing adds another condition: recovery from fewer measurements can be possible when the original signal is sparse and the measurement matrix has suitable properties. Sparsity alone does not guarantee recovery.

### properties

These are distinct questions about a representation:

- **Decomposability:** can we assign stable meanings to components across inputs?
- **Linearity:** can their contributions be approximated by the sum above?
- **Superposition:** are the represented directions linearly dependent? With columns $w_i$, this is equivalent to $W^\top W$ being singular. It necessarily holds when $m>d$.
- **Basis alignment:** does a feature align with an individual neuron, or use several coordinates in the model’s [[thoughts/basis|basis]]?

Several linearly independent features can each use many neurons. Keeping these questions separate prevents “distributed” and “superposed” from becoming interchangeable labels.

### importance

The toy model varies two quantities: how often a feature is active, and how heavily its reconstruction error contributes to the loss. The first controls sparsity; the second encodes importance. Changing either can change which features the trained model retains and how they share dimensions. \[@elhage2022superposition\]

### over-complete basis

“Overcomplete basis” usually means a dictionary with more vectors than the activation space has dimensions. It is linearly dependent, so it is not a basis in the strict linear-algebra sense. [[thoughts/sparse autoencoder|SAEs]] learn such dictionaries by seeking sparse reconstructions. The resulting directions are candidates for features, with their meaning and causal role still to check.

## features

A feature is a property represented in a model, such as a word’s grammatical role or the presence of an edge in an image. In toy models we choose the features ourselves. In a trained language model, identifying them is part of the research problem.

Word embeddings supply an early example of semantic directions. Their analogy results include approximate relations of the form

$$
v_{\mathrm{king}}-v_{\mathrm{man}}+v_{\mathrm{woman}}
\approx v_{\mathrm{queen}}.
$$

The operation retrieves a nearby word vector; it does not assert an exact identity or isolate every aspect of the words’ meanings. \[@mikolov-etal-2013-linguistic\]

The same burden applies when interpreting an SAE latent. Examples with high activation suggest a label. Held-out examples test the label’s coverage, and interventions test whether the direction affects the proposed computation.

## ablation

Ablation removes or replaces a chosen component’s contribution and measures how model behaviour changes. The component can be an activation, feature, attention head, or parameter subset.

- **Zero ablation:** replace the chosen activation with zero.
- **Mean ablation:** replace it with an average over a stated reference dataset.
- **Resample ablation:** replace it with an activation from another example, chosen according to a stated sampling rule.

The replacement defines the experiment. Zero can be atypical at a chosen site; a mean can erase context; resampling can introduce unrelated information. Record the task, replacement, and output metric. A drop in performance supports a contribution under that intervention, with the replacement’s side effects still to examine. An unchanged output can also reflect redundant paths. \[@heimersheim2024useinterpretactivationpatching\] Parameter pruning is a related use of removal, usually aimed at changing the model permanently.

## mathematical frameworks to transformers

see also: @elhage2021mathematical, [[thoughts/mathematical framework transformers circuits|notes]]

### residual stream



```jsx imports={Zoomable,ResidualStream}
<Zoomable label="residual stream diagram">
  <ResidualStream caption="Each attention head and MLP layer reads from and writes back into the same shared stream." />
</Zoomable>
```

For a sequence of $C$ tokens and model width $d$, write the residual stream as $x_0\in\mathbb{R}^{C\times d}$. An [[thoughts/Attention|attention]] sublayer computes an update and adds it to the stream:

$$
x_1=x_0+H(x_0).
$$

Here $H$ includes any normalization at that sublayer’s input. An MLP sublayer then adds its own update. Addition lets us track which component wrote a contribution and which later component reads it. The functions producing those updates remain nonlinear, and attention can move information between token positions.

![[thoughts/induction heads|induction heads]]

## grokking

Grokking is delayed generalization: training performance becomes good well before test performance improves. @power2022grokkinggeneralizationoverfittingsmall observed this on small algorithmic datasets.

For modular addition, a later [2301.05217](https://arxiv.org/abs/2301.05217) \[@nanda2023progressmeasuresgrokkingmechanistic\]  identified a learned algorithm using [[thoughts/Fourier transform|Fourier]] components. Its circuitry developed before the sharp rise in test accuracy. The Fourier structure describes that model’s algorithm; the delay in generalization is the phenomenon to explain.

see also: [author’s writeup](https://www.alignmentforum.org/posts/N6WM6hs7RQMKDhYjB/a-mechanistic-interpretability-analysis-of-grokking), [analysis notebook](https://colab.research.google.com/drive/1F6_1_cWXE5M7WocUcpQWp3v8z4b1jL20), [induction-head training dynamics](https://transformer-circuits.pub/2022/in-context-learning-and-induction-heads/index.html).

## attribution graph

An attribution graph describes a chosen output on one prompt. In [Circuit Tracing](https://transformer-circuits.pub/2025/attribution-graphs/methods.html), nodes are active CLT features, input embeddings, reconstruction errors, and logits. Direct edges become linear contributions after fixing attention patterns and normalization denominators at their observed values. See [[thoughts/circuit tracing|circuit tracing]] for the equations and [On the Biology of a Large Language Model](https://transformer-circuits.pub/2025/attribution-graphs/biology.html) for case studies.



```jsx imports={Zoomable,AttributionGraph}
<Zoomable label="attribution graph">
  <AttributionGraph caption="The acronym graph of Circuit Tracing, figure 5, redrawn: an 18-layer model reads 'The National Digital Analytics Group (N' and writes 'DAG'. Each box is a supernode; its sage bar is its activation. An edge carries $A_{s\to t}=a_s w_{s\to t}$ and its width follows that value. The paper ranks by path influence $B=(I-A)^{-1}-I$ instead. The weights are illustrative, chosen so every node's inputs sum to one; the paper's figure carries none, and the real test of any ablation runs in the original model." />
</Zoomable>
```

### parameter decomposition

[[thoughts/Attribution parameter decomposition|APD]] decomposes weights into sparsely used components. Those components can span several layers. Connecting them to an attribution graph requires a definition of their interactions and tests of the proposed edges.

### limitations

The replacement model can compute differently from the original. Pruning hides paths, and the graph is local to a forward pass. Frozen attention leaves the causes of its attention weights unexplained; [[thoughts/mechanistic interpretability#QK attributions|QK attributions]] examine how query and key features assign weight to source positions.

### applications

Circuit graphs guide mechanism discovery and candidate interventions. Anomaly detection, cross-model circuit transfer, and tracking how circuits emerge during training are research directions. Each needs its own evaluation: output agreement, correspondence between models, or evidence across training checkpoints.

## stochastic parameter decomposition

@bushnaq2025stochasticparameterdecomposition follows [[thoughts/Attribution parameter decomposition|APD]] with a stochastic ablation objective. Its experiments recover known mechanisms in toy models that are larger or more complex than the earlier APD examples, with improved robustness to hyperparameters. These results establish progress within that test suite; decomposition of large deployed models requires further evidence.

see also: [2506.20790](https://arxiv.org/abs/2506.20790) \[@bushnaq2025stochasticparameterdecomposition\] , [code](https://github.com/goodfire-ai/spd).

## QK attributions

[Tracing Attention Computation Through Feature Interactions](https://transformer-circuits.pub/2025/attention-qk) decomposes attention scores into interactions between query-side and key-side features. The score before softmax is bilinear in the query and key representations. Expanding both into feature contributions gives terms that help explain why an attention head selected particular tokens. Softmax still couples the resulting attention weights across candidate positions.

## manipulate manifolds

[When Models Manipulate Manifolds](https://transformer-circuits.pub/2025/linebreaks/index.html) studies how Claude 3.5 Haiku predicts line breaks in fixed-width text. Character counts lie along curved, low-dimensional representations. Attention heads transform those representations to compare the current count with the line width, then the model combines the space remaining with the next word’s length.

This gives a concrete reason to inspect feature geometry. Several discrete dictionary features can describe nearby parts of one counting representation. Parameterizing the count exposes the computation shared across those features, and targeted interventions test that account.

