Choosing an analysis tool¶
Start with the question you want to answer, then choose the measurement. A vocabulary readout, a geometric similarity score, and an intervention answer different questions, even when they highlight the same attention head or token.
This guide covers the high-level tools in transformer_lens.tools.analysis. For
capturing activations or installing your own interventions, start with the
hook system. New experiments should use TransformerBridge; see
the 4.0 migration guide for existing HookedTransformer code.
Choose by research question¶
I want to know… |
Start with |
Inputs and outputs |
What the result establishes |
|---|---|---|---|
Which components contribute to an answer’s logit? |
Direct Logit Attribution (DLA) |
A prompt or activation cache, answer token, and optional comparison token → labeled logit contributions. |
A decomposition of the residual-stream readout for that run. |
Which activation, if restored from the clean run, recovers the answer, and how sure am I per cell? |
Activation Patching |
Corrupted tokens, a clean cache and a metric → a grid of patched-metric values; with |
The measured effect of one causal intervention per cell, with its uncertainty across the prompt batch. |
Which activations or paths should I investigate with patching? |
Attribution Patching |
Aligned clean/corrupt token pairs and a differentiable scalar metric → signed node or edge scores. |
A first-order estimate of the effect of replacing corrupt activations with clean ones. |
Does a particular head-to-head route affect my metric? |
Direct Path Patching |
Clean/corrupt caches, a source head, and a metric → destination-head patch scores. |
The measured effect of the implemented path intervention, subject to its LayerNorm approximation. |
What does each layer “predict”, and where does a token’s rank change? |
Logit Lens |
A prompt or activation cache, optional target tokens, top-k or a vocabulary subset → per-layer logits, log-probabilities, ranks and entropy. |
What the residual stream reads as through the real final norm and unembedding; the final entry reproduces the model’s own logits. |
What vocabulary directions appear in an MLP’s gradient factors? |
Backward Lens |
A prompt, one target token, and selected layers → gradient factors and vocabulary rankings. |
A diagnostic of the forward inputs and backward signals composing a weight gradient. |
How can I read or edit residuals through a fitted transport map? |
Jacobian Lens |
A matching lens artifact and model, plus prompts or activations → vocabulary readouts, decompositions, or interventions. |
Readouts under the fitted map; causal effects require running and measuring an intervention. |
How much do two subspaces overlap? |
Projection Kernel |
Two subspace bases, or Bridge attention-head weight spaces → overlap scores and principal-angle information. |
Shared geometric support, independent of the choice of basis within each subspace. |
What are a head’s QK/OV singular directions? |
SVD Circuits: head decomposition |
Model weights and a layer/head index → singular values, vectors, and degeneracy reports. |
The linear structure of the head’s weight maps. |
These are starting points, not a required pipeline. For example, a weight-space comparison can motivate a patching experiment, but a large overlap score alone does not identify the head’s function or prove a causal connection.
Check model requirements before combining tools¶
A model appearing in the model tables does not imply that every analysis below supports its architecture. Tools also depend on weight processing, available hooks, and the meaning of the selected tensor axes.
Tool |
Requirements to check |
Main compute or memory cost |
|---|---|---|
DLA |
Targets TransformerBridge in 4.0. Enable compatibility mode and use the standard attention/MLP residual decomposition; Mamba/SSM/Mixer/LinearAttention hybrid layouts are rejected. |
One cached forward pass, or reuse of a suitable cache. Head decomposition can require additional per-head results. |
Activation Patching |
Any bridge whose activation names resolve ( |
One forward of the corrupted batch per swept cell (plus one for |
Attribution Patching |
Targets TransformerBridge. Clean/corrupt inputs must be |
Two forwards and one backward per prompt pair; activation and gradient caches. For a uniform-head decoder, the number of edge scores grows as |
Direct Path Patching |
Requires a TransformerBridge exposing the expected attention weights, Q/K/V hook aliases, source |
Clean/corrupt caching, then repeated forwards over destination heads. Sweeping all source heads adds another sweep dimension. |
Logit Lens |
Targets TransformerBridge, raw or compatibility mode. Needs a decoder with an |
One cached forward pass over the residual hooks, or reuse of a cache. Logits are produced in chunks of |
Backward Lens |
Requires a raw decoder-only TransformerBridge with dense, non-gated MLPs and without compatibility mode, such as GPT-2 or Pythia/GPT-NeoX. Use one target token and check the restrictions in the tool guide. |
Gradient computation plus vocabulary projections for selected layers and positions; retaining full logits increases memory. |
Jacobian Lens |
Requires a fresh, causal decoder-only Bridge with raw HF weights, without compatibility mode or weight processing. Validate the lens against the model. Fitting additionally requires all modules in evaluation mode. |
Loading an existing artifact avoids fitting. The ordinary fitting estimator uses one forward and |
Projection Kernel |
The numerical API accepts finite, real floating-point matrices via orthonormal bases. The attention-head wrapper requires Bridge weights with compatible dimensions and ranks. |
Basis extraction uses SVD. All-head comparisons allocate basis stacks and a pairwise score grid; they can be large despite requiring no forward pass. |
SVD head decomposition |
Uses Bridge per-block weight accessors; requires accessible, compatible |
Factored QK/OV SVD, with rank bounded by |
Compatibility mode is a method-specific choice. DLA needs it on Bridge, whereas Jacobian Lens requires raw weights. Use separately loaded models when comparing these workflows, and collect each cache from the model configuration that will consume it. Do not reuse a cache after changing weights or processing mode. See compatibility mode for the numerical conventions.
Evaluation mode and gradient recording are separate choices: model.eval() disables
training behavior such as dropout; it does not disable autograd. Do not wrap a
gradient-based analysis in torch.no_grad() or torch.inference_mode().
Read the output with the right interpretation¶
DLA: contributions, not ablation effects¶
Use direct_logit_attribution(..., unit="component") for additive component
contributions, or unit="head" for heads plus a remainder. With unit="layer",
the entries are cumulative residual readouts after sublayers, not independent
contributions to sum together.
An answer-minus-comparison-token direction often makes the question more specific
than a single answer logit. String answers must encode to one token; a leading space
can change tokenization. A complete component decomposition accounts for the
residual contribution, so the unembedding bias b_U is excluded. Removing a component
can change downstream computation, so its DLA score is not its ablation effect.
Activation Patching: per-example cells, then intervals¶
Every get_act_patch_* sweep runs the whole corrupted batch for each patched
cell, so the per-example values are free. Pass a metric that returns a [batch]
tensor and reduce="none" to keep them: the result is a PatchingResult whose
values end in a batch axis, with mean(), stderr(), bootstrap_ci() and, when
the sweep was run with baseline=True, effect() (patched minus unpatched
corrupted run) and permutation_pvalue(). reduce="mean" averages a [batch]
metric back to the plain tensor the sweeps have always returned, and a mapping of
metrics is evaluated on each patched forward so two metrics cost one sweep.
Read the statistics for what they are. The bootstrap interval describes how the cell’s mean would move across resamples of these prompts; with four to eight prompts it is wide, and a constant column collapses it to a point. The sign-flip permutation test asks whether the per-example effects are symmetric about zero; it is exact for twelve or fewer prompts and a Monte Carlo estimate above that. Neither says anything about prompts outside the batch, and neither changes what a single cell establishes: the measured effect of one intervention.
Attribution Patching: screen candidates, then measure interventions¶
At node granularity, the score uses
(clean_activation - corrupt_activation) · corrupt_gradient. At edge granularity,
EdgeAttributionConfig(granularity="edge") scores each writer-to-reader path
using the writer’s activation difference and the gradient at that reader’s input;
edge_scores and top_edges() expose those paths, while node_scores aggregates
the outgoing edge scores for each writer. A positive score predicts an increase
in the chosen metric when moving the corrupt activation toward the clean one.
Reversing the metric reverses this interpretation. Large activation changes and
nonlinear downstream behavior can make the estimate inaccurate; compare promising
candidates with actual activation replacements using the hook system.
Both node and edge granularity use plain attribution with ig_steps=1.
ig_steps>1 still raises NotImplementedError; EAP-IG is not available yet.
API: attribution_patch().
Direct Path Patching: state the path and its approximation¶
get_act_patch_direct_path fixes a source head and sweeps later destination heads,
patching into their Q, K, or V inputs. It reconstructs the source head’s output from
cached hook_z and W_O, so caching hook_result is unnecessary. The calculation
projects the source-output change using cached LayerNorm scaling; it does not
recompute the full nonlinear normalization response to that change. Folded
parameters do not remove this fixed-scale assumption.
Interpret a score relative to the unpatched corrupt metric. Entries at or before the source layer are zero placeholders, not measured interventions. State the source head, destination input, prompt pair, and normalization convention when reporting a path.
Logit Lens: read the stream through the real norm¶
logit_lens(model, prompt) (or cache.logit_lens()) applies the model’s own
ln_final with recomputed statistics, then W_U, b_U and the adapter’s output
transform (Gemma-style softcap, Cohere logit scale) to every entry of the
accumulated residual stream. Its final entry equals the model’s logits on a raw
bridge; in compatibility mode center_unembed shifts every logit by a per-position
constant, so compare return_type="log_probs" or ranks across processing modes, not
raw logits. apply_ln=False reads the unnormalized stream and does not reproduce the
model.
targets= reports each token’s logit and its full-vocabulary rank at every layer
(result.rank_trajectory(" Paris")); a [batch, pos] tensor of next-token ids
instead gives the rank of the actual next token at every position and layer,
without materializing the full vocabulary; top_k= keeps the leading tokens with
their ids; vocab= keeps a subset. Ranks, entropy and log-probabilities are always
computed over the full vocabulary, whatever was selected. logit_readout is the
same kernel for any d_model vector: a head output, a steering direction, a
sparse-coder decoder column.
Intermediate-layer readouts are observations, not interventions. A token ranked first at layer 6 is what the unembedding would say if the model stopped there; it does not establish that later layers are inert, and the recomputed norm can magnify a small early residual. Pair a lens trajectory with patching or DLA before making a causal claim. For a fitted per-layer map instead of the identity, see Jacobian Lens.
Backward Lens: preserve the gradient sign¶
Vocabulary rankings describe factors of d(loss) / d(weight). Gradient descent
subtracts this gradient. The highest raw-gradient token is therefore not
automatically the token favored by an update. Use the documented bottom rankings
and gradient-descent target ranks where appropriate. Align positions using
result.prompt_token_ids, which records the actual tokenization.
See Backward Lens for the example, sign conventions, and result structure.
Jacobian Lens: distinguish readout, reconstruction, and intervention¶
Start with a matching published artifact when possible and call
lens.validate_model(model). Pin model and artifact revisions. A vocabulary readout
uses the fitted transport map; sparse decomposition describes an activation in its
dictionary. A small reconstruction error does not establish that editing a
coordinate will cause the predicted answer.
For a causal question, install the relevant hooks and measure model outputs against an unedited baseline and suitable controls. Check the selected intervention’s layer and position semantics: a multi-layer edit is not generally equivalent to independent single-layer edits.
See fitting and provenance and the decomposition demo.
Weight-space tools: use geometry to form hypotheses¶
Projection Kernel compares subspaces, without measuring weight magnitude or model
behavior on a prompt. In attention-head results, use valid_mask when interpreting
scores: invalid pairs are stored as zeros. See Projection Kernel
for rank selection, normalization, and all-head memory costs.
For SVD head decomposition, inspect the rank report before assigning meaning to an individual direction. Near-equal singular values define a subspace whose basis can rotate; numerically null directions are also unsuitable for individual attribution. The weight decomposition alone is not a causal validation of a proposed subfunction.
API: decompose_head().
Try a geometry question without downloading a model¶
The following subspaces share exactly one axis. Their raw Projection Kernel score is 1, and the normalized score is 0.5 because both have rank 2.
import torch
from transformer_lens.tools.analysis import orthonormal_subspace, projection_kernel
axes = torch.eye(3)
first = orthonormal_subspace(axes[:, [0, 1]])
second = orthonormal_subspace(axes[:, [0, 2]])
result = projection_kernel(first, second)
print(result.score.item()) # 1.0
print(result.normalized.item()) # 0.5
Replacing these matrices with head-weight bases gives a geometric comparison of heads. Establishing what those heads do still requires prompts and behavioral measurements.
Plan a focused experiment¶
For a question such as “which components help the model prefer Paris to London?”:
Define the prompt set, answer token ids, final position, and signed logit-difference metric. Check the unmodified model’s answers before interpreting an intervention.
Use DLA for a readout decomposition, or aligned clean/corrupt pairs with Attribution Patching to shortlist intervention candidates. These scores need not agree because they measure different quantities.
Replace selected activations and record the observed metric change. Add a no-op replacement to check the hook setup and controls matched to the experimental claim, such as alternative sites or perturbations of comparable magnitude.
Inspect per-prompt results before aggregating. Report failures and exclusions, and evaluate the hypothesis on held-out prompts when making a general claim.
Record model/tokenizer revisions, dtype, weight-processing mode, token ids, hook names, positions, metric definition, and any lens artifact or random seed.
The goal is to connect an interpretable measurement to a clearly specified experiment, with enough information for another researcher to repeat it.