transformer_lens.tools.analysis package¶
Submodules¶
- transformer_lens.tools.analysis.attribution_patching module
AttributionResultEdgeAttributionConfigFaithfulnessConfigFaithfulnessResultFaithfulnessResult.recoveredFaithfulnessResult.full_metricFaithfulnessResult.corrupt_metricFaithfulnessResult.circuit_sizeFaithfulnessResult.total_edgesFaithfulnessResult.edge_class_recoveredFaithfulnessResult.edge_class_countsFaithfulnessResult.circuit_sizeFaithfulnessResult.corrupt_metricFaithfulnessResult.edge_class_countsFaithfulnessResult.edge_class_recoveredFaithfulnessResult.full_metricFaithfulnessResult.recoveredFaithfulnessResult.total_edges
GradientCacheNodeattribution_patch()cache_activation_and_gradient()capture_writer_outputs()enumerate_edges()enumerate_nodes()faithfulness()
- transformer_lens.tools.analysis.direct_logit_attribution module
- transformer_lens.tools.analysis.direct_path_patching module
- transformer_lens.tools.analysis.interchange module
DASResultInterventionLearnedSubspaceNeuronsNormMatchedPlaceboSubspaceInterchangeTaskLogitsarbitrary_targets()collect_activations()fit_das()intervened_logits()mean_difference_basis()neuron_basis()probe_basis()random_basis()random_init_bridge()random_neuron_basis()reinitialized()run_with_intervention()
- transformer_lens.tools.analysis.jacobian_lens module
JacobianLensJacobianLens.jacobiansJacobianLens.n_promptsJacobianLens.d_modelJacobianLens.metadataJacobianLens.ablation_hooks()JacobianLens.clear_device_cache()JacobianLens.coordinate_patch()JacobianLens.coordinate_patch_hooks()JacobianLens.decompose()JacobianLens.fit()JacobianLens.fraction_of_variance()JacobianLens.from_pretrained()JacobianLens.lens_vector_dictionary()JacobianLens.lens_vectors()JacobianLens.load()JacobianLens.merge()JacobianLens.occupancy()JacobianLens.readout()JacobianLens.save()JacobianLens.source_layersJacobianLens.steering_hooks()JacobianLens.swap_clamp_hooks()JacobianLens.swap_hooks()JacobianLens.transport()JacobianLens.validate_model()
JacobianLensReadoutJacobianLensReadout.lens_topk_valuesJacobianLensReadout.lens_topk_indicesJacobianLensReadout.model_topk_valuesJacobianLensReadout.model_topk_indicesJacobianLensReadout.lens_logitsJacobianLensReadout.model_logitsJacobianLensReadout.tokensJacobianLensReadout.positionsJacobianLensReadout.use_jacobianJacobianLensReadout.lens_logitsJacobianLensReadout.lens_topk_indicesJacobianLensReadout.lens_topk_valuesJacobianLensReadout.model_logitsJacobianLensReadout.model_topk_indicesJacobianLensReadout.model_topk_valuesJacobianLensReadout.positionsJacobianLensReadout.tokensJacobianLensReadout.top_tokens()JacobianLensReadout.use_jacobian
- transformer_lens.tools.analysis.jacobian_lens_coordinate_patch module
CoordinatePatchCoordinatePatch.support_beforeCoordinatePatch.support_afterCoordinatePatch.coordinates_beforeCoordinatePatch.coordinates_afterCoordinatePatch.source_slotCoordinatePatch.target_slotCoordinatePatch.target_was_appendedCoordinatePatch.target_was_selectedCoordinatePatch.overwritten_target_coordinateCoordinatePatch.reconstruction_beforeCoordinatePatch.reconstruction_afterCoordinatePatch.residualCoordinatePatch.deltaCoordinatePatch.patchedCoordinatePatch.nonedited_coordinate_max_deltaCoordinatePatch.residual_max_deltaCoordinatePatch.source_target_cosineCoordinatePatch.basis_rankCoordinatePatch.basis_condition_numberCoordinatePatch.coordinates_after_nonnegativeCoordinatePatch.basis_condition_numberCoordinatePatch.basis_rankCoordinatePatch.coordinates_afterCoordinatePatch.coordinates_after_nonnegativeCoordinatePatch.coordinates_beforeCoordinatePatch.deltaCoordinatePatch.nonedited_coordinate_max_deltaCoordinatePatch.overwritten_target_coordinateCoordinatePatch.patchedCoordinatePatch.reconstruction_afterCoordinatePatch.reconstruction_beforeCoordinatePatch.residualCoordinatePatch.residual_max_deltaCoordinatePatch.source_slotCoordinatePatch.source_target_cosineCoordinatePatch.support_afterCoordinatePatch.support_beforeCoordinatePatch.target_slotCoordinatePatch.target_was_appendedCoordinatePatch.target_was_selected
solve_coordinate_patch()solve_coordinate_patch_positions()
- transformer_lens.tools.analysis.jacobian_lens_decomposition module
DEFAULT_KJSpaceDecompositionJSpaceDecomposition.supportJSpaceDecomposition.coordinatesJSpaceDecomposition.selected_supportJSpaceDecomposition.reconstructionJSpaceDecomposition.j_space_componentJSpaceDecomposition.non_j_space_componentJSpaceDecomposition.coordinatesJSpaceDecomposition.j_space_componentJSpaceDecomposition.non_j_space_componentJSpaceDecomposition.reconstructionJSpaceDecomposition.selected_supportJSpaceDecomposition.support
JSpaceOccupancyJSpaceVarianceProfileestimate_occupancy()get_sparse_decomposition()
- transformer_lens.tools.analysis.logit_lens module
LogitLensResultLogitLensResult.readoutLogitLensResult.labelsLogitLensResult.has_batch_dimLogitLensResult.target_namesLogitLensResult.has_batch_dimLogitLensResult.labelsLogitLensResult.rank_trajectory()LogitLensResult.readoutLogitLensResult.target_namesLogitLensResult.to_dataframe()LogitLensResult.top_tokens()LogitLensResult.values
LogitReadoutLogitReadout.valuesLogitReadout.return_typeLogitReadout.entropyLogitReadout.top_idsLogitReadout.vocab_idsLogitReadout.target_idsLogitReadout.target_ranksLogitReadout.per_row_targetsLogitReadout.applied_lnLogitReadout.applied_output_transformLogitReadout.applied_lnLogitReadout.applied_output_transformLogitReadout.decode()LogitReadout.entropyLogitReadout.per_row_targetsLogitReadout.return_typeLogitReadout.row_ids()LogitReadout.selected_idsLogitReadout.target_idsLogitReadout.target_ranksLogitReadout.top_idsLogitReadout.valuesLogitReadout.vocab_ids
logit_lens()logit_readout()
- transformer_lens.tools.analysis.projection_kernel module
AttentionHeadRefHeadAffinityPairHeadAffinityResultHeadAffinityResult.normalizedHeadAffinityResult.rankHeadAffinityResult.rtolHeadAffinityResult.scoresHeadAffinityResult.source_head_kindHeadAffinityResult.source_layer_indicesHeadAffinityResult.source_rankHeadAffinityResult.source_ranksHeadAffinityResult.source_roleHeadAffinityResult.target_head_kindHeadAffinityResult.target_layer_indicesHeadAffinityResult.target_rankHeadAffinityResult.target_ranksHeadAffinityResult.target_roleHeadAffinityResult.top_pairs()HeadAffinityResult.valid_mask
ProjectionKernelResultRandomSubspaceReferenceSubspaceBasisSubspaceBasis.basisSubspaceBasis.singular_valuesSubspaceBasis.rankSubspaceBasis.measured_rankSubspaceBasis.rtolSubspaceBasis.thresholdSubspaceBasis.input_shapeSubspaceBasis.ambient_dimSubspaceBasis.basisSubspaceBasis.input_shapeSubspaceBasis.measured_rankSubspaceBasis.rankSubspaceBasis.rtolSubspaceBasis.singular_valuesSubspaceBasis.threshold
attention_head_subspace_affinity()orthonormal_subspace()projection_kernel()random_projection_kernel_moments()
- transformer_lens.tools.analysis.sparse_probing module
SparseProbeControlSparseProbeConvergenceErrorSparseProbeMetricsSparseProbeMetrics.accuracySparseProbeMetrics.average_precisionSparseProbeMetrics.f1SparseProbeMetrics.false_negativesSparseProbeMetrics.false_positivesSparseProbeMetrics.precisionSparseProbeMetrics.recallSparseProbeMetrics.roc_aucSparseProbeMetrics.true_negativesSparseProbeMetrics.true_positives
SparseProbeRejectionSparseProbeResultSparseProbeResult.class_weightSparseProbeResult.coefficientsSparseProbeResult.constant_featuresSparseProbeResult.decrement_toleranceSparseProbeResult.feature_scoresSparseProbeResult.function_evaluationsSparseProbeResult.gradient_inf_normSparseProbeResult.interceptSparseProbeResult.iterationsSparseProbeResult.kSparseProbeResult.l2_strengthSparseProbeResult.max_iterSparseProbeResult.max_refinement_stepsSparseProbeResult.metricsSparseProbeResult.negative_labelSparseProbeResult.newton_decrementSparseProbeResult.objectiveSparseProbeResult.positive_labelSparseProbeResult.preprocessSparseProbeResult.preprocess_meanSparseProbeResult.preprocess_scaleSparseProbeResult.refinement_stepsSparseProbeResult.seedSparseProbeResult.selected_featuresSparseProbeResult.std_floorSparseProbeResult.stop_reasonSparseProbeResult.test_fractionSparseProbeResult.test_indicesSparseProbeResult.test_negative_countSparseProbeResult.test_positive_countSparseProbeResult.train_indicesSparseProbeResult.train_negative_countSparseProbeResult.train_positive_count
SparseProbeSweepfit_sparse_probe()sweep_sparse_probe()
Module contents¶
Analysis tools for TransformerLens.
This subpackage collects high-level, single-call interpretability analyses that
sit on top of the hook/cache system. Model support is documented per tool;
new analyses may target the TransformerBridge API exclusively.
Entry points and the classes they accept are exported here; result dataclasses stay in the module that returns them.
- Tools:
attribution_patching: Attribution patching (gradient-linearized activation patching) over residual-stream nodes and edges: typed computational graph, a names-filtered manual-backward gradient cache, and signed node and edge scores (EAP), plus forward-only ablate-outside faithfulness with corrupt or held-out mean replacements and circuit-relative class diagnostics. Integrated gradients (EAP-IG) are not implemented.
direct_logit_attribution: Direct Logit Attribution (DLA) over components, layers, or attention heads.
get_act_patch_direct_path, get_act_patch_direct_path_all_sources: re-exported from
transformer_lens.patching; exact direct path patching for head-to-head circuit analysis.interchange: Interchange interventions on linear subspaces: set a base’s activation inside a subspace to its value on a source input, with difference-of-means, probe, random and neuron bases, a norm-matched placebo, batched gradient-free evaluation, distributed alignment search (DAS) to learn the subspace, and DAS’s trained controls (arbitrary labels and a randomly initialised model).
jacobian_lens: The Jacobian lens (J-lens) — per-layer causal transport to the output vocabulary basis, with loading of published lens artifacts, native fitting, readouts, interventions, J-space sparse decomposition, and anchored coordinate patching (offline and dynamic/hooked).
logit_lens: One-call logit lens over the accumulated residual stream and the
logit_readoutkernel that reads anyd_modelvector through the real final norm, unembedding and adapter output transform, chunked over the vocabulary with target ranks, top-k and vocabulary subsets.projection_kernel: Basis-invariant subspace overlap and TransformerBridge attention-head OQ/OK/OV affinity.
sparse_probing: Leakage-safe k-sparse binary probes over supplied activation tensors, with train-only selection and raw null controls.
- class transformer_lens.tools.analysis.EdgeAttributionConfig(granularity: Literal['node', 'edge'] = 'node', ig_steps: int = 1)¶
Bases:
objectConfiguration for an attribution-patching sweep.
The two axes are deliberately orthogonal:
granularityselects what is scored:"node"scores each residual-stream write,"edge"scores each(source, destination)write->read pair.ig_stepsselects gradient fidelity.ig_steps=1is plain attribution patching / EAP: a single first-order Taylor gradient taken at the corrupt point.ig_steps>1is EAP-IG: the integrated gradient averaged over that many points along the corrupt->clean path, which corrects the gradient saturation that makes plain attribution unfaithful.
There is intentionally no
methodfield. An earlier design had both amethodenum ("attribution"/"EAP"/"EAP-IG") andig_steps, which overlap: the method is fully determined bygranularityand whetherig_stepsexceeds 1. Collapsing them removes the invalid states (e.g.method="attribution", ig_steps=5).This build implements node and edge granularity with plain attribution.
ig_steps>1is accepted by the type but raisesNotImplementedErrorat construction, so downstream code can import and reference this API now while the integrated-gradient path is not implemented. Once EAP-IG lands, the default flips toig_steps=5(EAP-IG is the faithful default); until then the default is the only executable value,ig_steps=1.- granularity¶
"node"or"edge". Defaults to"node".- Type:
Literal[‘node’, ‘edge’]
- ig_steps¶
Integrated-gradient path steps (
>=1). Defaults to1.- Type:
int
- granularity: Literal['node', 'edge'] = 'node'¶
- ig_steps: int = 1¶
- class transformer_lens.tools.analysis.FaithfulnessConfig(ablation: Literal['corrupt', 'mean'] = 'corrupt')¶
Bases:
objectConfiguration for an ablate-outside faithfulness measurement.
- ablation¶
How an out-of-circuit edge’s writer is replaced.
"corrupt"(default) substitutes the corrupt run’s own contribution;"mean"substitutes that writer’s mean over the held-outmean_tokensbatch passed tofaithfulness().- Type:
Literal[‘corrupt’, ‘mean’]
- ablation: Literal['corrupt', 'mean'] = 'corrupt'¶
- class transformer_lens.tools.analysis.JSpaceDecomposition(support: Tensor, coordinates: Tensor, selected_support: Tensor, reconstruction: Tensor, j_space_component: Tensor, non_j_space_component: Tensor)¶
Bases:
objectResult of a sparse J-space decomposition.
- support¶
Indices of the numerically active selected atoms – those whose nonnegative coordinate materially contributes (token ids when the dictionary is the vocabulary of J-lens vectors). A subset of
selected_support.- Type:
torch.Tensor
- coordinates¶
Nonnegative pursuit coefficients aligned with
support(the “local J-space coordinates”); every entry is materially nonzero.- Type:
torch.Tensor
- selected_support¶
Indices of every greedily selected atom, including any whose coordinate was driven to zero by the nonnegativity constraint. Defines the span for
j_space_component. Satisfiessupport.numel() <= selected_support.numel() <= k.- Type:
torch.Tensor
- reconstruction¶
The nonnegative combination
sum(coordinates * active atoms)oversupport.- Type:
torch.Tensor
- j_space_component¶
The orthogonal projection of the target onto the span of
selected_support(the paper’s “J-space component”). For the exact NNLS re-solve it equalsreconstructionunless a selected atom has a zero coordinate, in which case the projection uses a larger span. Numerical rank is measured on unit atom columns in float64 with relative tolerancesqrt(eps64), independently of ambient dimension and atom norms.- Type:
torch.Tensor
- non_j_space_component¶
The residual
target - j_space_component(the “non-J-space component”), orthogonal to the selected span.- Type:
torch.Tensor
- coordinates: Tensor¶
- j_space_component: Tensor¶
- non_j_space_component: Tensor¶
- reconstruction: Tensor¶
- selected_support: Tensor¶
- support: Tensor¶
- class transformer_lens.tools.analysis.JacobianLens(jacobians: Dict[int, Float[Tensor, 'd_model d_model']], *, n_prompts: int, d_model: int, metadata: Dict[str, Any] | None = None)¶
Bases:
objectA fitted Jacobian lens: one transport matrix per source layer.
Layer convention (matching the reference implementation and the published artifacts): index
lrefers to the output of blocklat the Bridge-native hookblocks.{l}.hook_out.J[l]maps that activation to the final block’s output, pre final norm. The final layer itself is never fitted (its transport is the identity), sosource_layers == [0, ..., n_layers - 2]for a full fit.- jacobians¶
{layer: [d_model, d_model]}transport matrices, fp32, CPU.
- n_prompts¶
Number of prompts averaged into the fit.
- d_model¶
Residual stream width the lens was fitted for.
- metadata¶
Optional provenance (model name, TransformerLens version, fit hyperparameters). Preserved by
save()/load(); artifacts from the reference implementation load with empty metadata.
- ablation_hooks(model: Any, tokens: str | int | Sequence[str | int], layers: Sequence[int], *, positions: Sequence[int] | None = None) List[Tuple[str, Any]]¶
Hooks that project token directions out of the residual stream.
With an orthonormal basis
Qof the span of the tokens’ lens vectors:h <- h - Q Qᵀ h, sohends with zero projection onto every requested vector. For a single token this ish - (h·v̂) v̂.- Parameters:
model – The model the hooks will run on.
tokens – Concept token(s) to suppress.
layers – Layers to intervene at.
positions – Chunk-local positions to ablate (negative indices allowed and normalized on every hook invocation). Defaults to all.
- Returns:
[(hook_name, fn), ...]formodel.hooks(fwd_hooks=...).
- clear_device_cache() None¶
Release cached Jacobians, dictionaries, and unembedding snapshots on devices.
- coordinate_patch(model: Any, activation_or_prompt: Tensor | str, layer: int, source_token: str | int, target_token: str | int, *, position: int | None = None, decomposition: JSpaceDecomposition | None = None, k: int = 25, mode: str = 'substitute', alpha: float = 1.0, algorithm: str = 'nonnegative_orthogonal_matching_pursuit') CoordinatePatch¶
Patch sparse J-space coordinates for an activation at
layer.The activation may be a raw
[d_model]vector or a prompt paired withposition, exactly as indecompose().source_tokenmust occur in the active sparse support.substitutereplaces the target coordinate with the source coordinate and zeros the source;swapexchanges them. Other coordinates andx - reconstructionare fixed.A supplied
decompositionavoids repeating the vocabulary-scale sparse solve after its activation and dictionary compatibility have been validated.- Parameters:
model – A raw
TransformerBridge.activation_or_prompt – An activation vector, or a prompt (string / token tensor).
layer – Source layer (must be a fitted source layer).
source_token – Active source concept, as a single-token string or token id.
target_token – Distinct target concept, as a single-token string or token id.
position – Token position when a prompt is given;
Nonefor a raw activation.decomposition – Optional compatible decomposition of this activation and dictionary.
k – Sparse-solver upper bound when
decompositionis not supplied.mode –
"substitute"or"swap".alpha – Finite interpolation strength; zero is an exact no-op.
algorithm – Sparse coefficient-update rule when
decompositionis not supplied. A supplied decomposition is accepted if it fits as either algorithm’s output.
- Returns:
A
CoordinatePatchcontaining the edited frame, diagnostics, and activation.
- coordinate_patch_hooks(model: Any, source_token: str | int, target_token: str | int, layers: Sequence[int], *, positions: Sequence[int], decomposition_cache: MutableMapping[Tuple[int, int, int], JSpaceDecomposition] | None = None, k: int = 25, mode: str = 'substitute', alpha: float = 1.0, algorithm: str = 'nonnegative_orthogonal_matching_pursuit') List[Tuple[str, Any]]¶
Hooks that anchor-patch one J-space coordinate live, per forward-pass position.
Unlike
coordinate_patch(), which edits one already-captured activation offline, this installs a forward hook that solvessolve_coordinate_patch()independently for every(batch_idx, position)pair at each requested layer – a vocabulary-scale sparse decomposition per pair, per hook firing, unlessdecomposition_cachesupplies one already validated for that(layer, batch_idx, position)key.- Parameters:
model – The model the hooks will run on.
source_token – Active source concept, as a single-token string or token id.
target_token – Distinct target concept, as a single-token string or token id.
layers – Layers to intervene at.
positions – Chunk-local positions to patch (negative indices allowed and normalized on every hook invocation). Required – there is no full-sequence default, because a silent default would trigger a vocabulary-scale solve at every position.
decomposition_cache – Optional caller-owned mapping from
(layer, batch_idx, position)to a previously validatedJSpaceDecomposition. A hit skips the vocabulary-scale scan; a miss solves and populates the cache. Purely a performance path – correctness does not depend on it.k – Sparse-solver upper bound on a cache miss.
mode –
"substitute"or"swap".alpha – Finite interpolation strength; zero is an exact no-op.
algorithm – Sparse coefficient-update rule on a cache miss. A cache hit is accepted if it fits as either algorithm’s output.
- Returns:
[(hook_name, fn), ...]formodel.hooks(fwd_hooks=...).- Raises:
ValueError – If
positionsis empty, ifsource_tokenandtarget_tokenresolve to the same id, or ifsource_tokenis not in the top-kactive support of every patched(batch_idx, position)pair at the moment its hook fires – the whole forward pass fails rather than silently patching a subset. This precondition is stronger and more order-dependent than “active on a clean forward pass”: in a band of layers an earlier hook’s patch edits the residual that a later layer re-decomposes, andsubstitute/swapzero or move the source coordinate, so the source can be removed from a later layer’s active support even though it was active on an unhooked pass. Stacking layers or positions therefore makes this progressively harder to satisfy.- Warns:
UserWarning – Once per call, naming the number of layers and positions that will perform a live vocabulary-scale solve on every cache miss.
- decompose(model: Any, activation_or_prompt: Tensor | str, layer: int, *, position: int | None = None, k: int = 25, algorithm: str = 'nonnegative_orthogonal_matching_pursuit') JSpaceDecomposition¶
Decompose an activation into its J-space content at
layer.activation_or_promptis either:a raw activation vector of shape
[d_model](leavepositionasNone), ora prompt – a string or a
[1, seq]token tensor – in which casepositionselects the token whoseblocks.{layer}.hook_outactivation is decomposed.
The full-vocabulary dictionary at
layeris built (and cached) vialens_vector_dictionary(), thenget_sparse_decomposition()solves for ak-sparse nonnegative combination of J-lens vectors.- Parameters:
model – A raw
TransformerBridge.activation_or_prompt – An activation vector, or a prompt (string / token tensor).
layer – Source layer (must be a fitted source layer).
position – Token position when a prompt is given; must be
Nonefor a raw activation vector.k – Upper bound on the number of J-lens vectors to select; selection stops early once no unselected vector is materially positively correlated, so fewer may be returned.
algorithm – Coefficient-update rule; see
get_sparse_decomposition().
- Returns:
A
JSpaceDecomposition. Itssupport(token ids here) holds only the numerically active J-lens vectors andselected_supportevery selected vector, withsupport.numel() <= selected_support.numel() <= k.supportand its token-decoding tensors are on CPU; the vector-valued outputs stay on the model’s device.- Raises:
ValueError – On an invalid model, a mismatched activation shape, a batched prompt, a prompt while the model is in training mode, an unfitted layer, or an invalid
k/algorithm.RuntimeError – If the default nonnegative least-squares solver cannot validate its result against the KKT conditions.
- classmethod fit(model: Any, prompts: Sequence[str], *, corpus: str, source_layers: Sequence[int] | None = None, dim_batch: int = 8, max_seq_len: int = 128, skip_first_positions: int = 16, show_progress: bool = True, metadata: Dict[str, Any] | None = None) JacobianLens¶
Fit a Jacobian lens on a hooked model.
Implements the reference estimator exactly. For each prompt: one forward pass (the prompt replicated
dim_batchtimes along the batch axis), thenceil(d_model / dim_batch)backward passes. Each backward plants a one-hot cotangent for one output dimension at every valid target position simultaneously — causal attention guarantees the gradient at source positiontis then the sum over target positionst' >= twith no explicit masking. Rows are averaged over valid source positions (the firstskip_first_positionsand the final position are excluded), and prompts contribute equally to the final mean. There is no randomness: the computation is deterministic given the prompts.The reference implementation reports that fit quality saturates quickly — on the order of 100 prompts of 128 tokens is usable; the published lenses use up to 1000. Use
merge()to parallelize across prompt slices.- Parameters:
model – A raw
TransformerBridge. Model parameters are temporarily frozen (requires_grad=False) during fitting and restored after. Cotangents and activation gradients use the model dtype; fit with a float32 model for the highest-fidelity estimator. The model and all of its submodules must be in evaluation mode.prompts – Prompt strings. Prompts too short to contain a valid position (
seq_len <= skip_first_positions + 1) are skipped with a warning and do not count towardn_prompts.corpus – Stable identifier for the prompt corpus or slice, recorded in artifact provenance.
source_layers – Layers to fit. Defaults to every layer below the final layer. Negative indices count from
n_layers.dim_batch – Output dimensions per backward pass. Higher is faster but replicates the prompt
dim_batchtimes in memory; total backward FLOPs are unchanged.max_seq_len – Prompts are truncated to this many tokens.
skip_first_positions – Leading positions excluded from the source average.
show_progress – Show a tqdm progress bar over prompts.
metadata – Extra provenance merged into
metadata.
- Returns:
The fitted
JacobianLens.- Raises:
TypeError – If model is not a
TransformerBridge.ValueError – On compatibility mode, training mode, invalid provenance or layer indices, or if no prompt was long enough to fit on.
- fraction_of_variance(model: Any, prompts: str | Tensor | Sequence[str | Tensor], layers: Sequence[int] | None = None, *, k: int = 25, skip_first: int = 16, positions: Sequence[int] | None = None, show_progress: bool = False) JSpaceVarianceProfile¶
Profile the J-space share of activation variance over a prompt corpus.
Each prompt is run once (caching
blocks.{layer}.hook_outfor every requested layer). At each sampled position the activation is decomposed and its J-space variance fraction||j_space_component||^2 / ||activation||^2is recorded. The numerator is thej_space_component– the orthogonal projection of the activation onto the span of the selected support (the paper’s appendix “J-space component”), not the nonnegativereconstruction; the two coincide only when every selected atom stays active. Per layer the profile reports the median of those fractions and the pooled ratiosum(||j_space_component||^2) / sum(||activation||^2)(the paper’s “fraction of total variance”).A layer that samples no positions – every prompt shorter than
skip_first, or only zero-norm activations – contributes no fractions: itsmedianandpooledarefloat("nan")and itsper_positiontensor is empty.- Parameters:
model – A raw
TransformerBridge.prompts – A prompt, or a sequence of prompts. Each token tensor must represent exactly one prompt and have shape
[1, seq].layers – Source layers to profile; defaults to all fitted
source_layers.k – Number of J-lens vectors per decomposition.
skip_first – Non-negative index before which positions are skipped (mirrors the fit’s early-position skip); not used for sampling when
positionsis given.positions – Explicit positions to sample instead of
skip_firstonward.show_progress – Show a tqdm progress bar over prompts.
- Returns:
A
JSpaceVarianceProfile.- Raises:
ValueError – On an invalid model, an unfitted layer, an empty corpus, a negative
skip_first, a token tensor that does not have shape[1, seq], or a model in training mode.
- classmethod from_pretrained(name_or_path: str, *, filename: str = 'lens.pt', revision: str | None = None, model: Any = None) JacobianLens¶
Load a lens from a local path, a short model name, or a Hub repo.
Resolution order¶
Local file — if name_or_path is an existing
.ptfile, load it directly.Local directory — if name_or_path is a directory, load
<name_or_path>/<filename>.Registry short name or HF model ID — if name_or_path matches a key or alias in the bundled
jacobian_lens_registry.json(e.g."gemma-2-2b"or"google/gemma-2-2b"), the corresponding artifact inneuronpedia/jacobian-lensis fetched automatically, at the commit the registry pins unless revision is given. The filename argument is ignored in this case because the registry already encodes the correct subpath.Explicit Hub repo — otherwise name_or_path is treated as a Hub repo id and filename is used as-is, preserving full backward compatibility (e.g.
from_pretrained("neuronpedia/jacobian-lens", filename="gpt2-small/jlens/...")).
- param name_or_path:
A local
.ptfile, a local directory, a short model name such as"gemma-2-2b"or"llama3.1-8b", a Hugging Face model ID such as"google/gemma-2-2b", or an explicit Hub repo id paired with filename.- param filename:
File (or subpath) inside a local directory or an explicit Hub repo. Ignored when name_or_path resolves via the registry.
- param revision:
Optional Hub revision (branch, tag, or commit). When omitted, registry names resolve at the registry’s pinned commit and an explicit Hub repo follows its mutable default branch; pin a commit hash for reproducible analyses of the latter.
- param model:
If given,
validate_model()is called so dimension or weight-processing mismatches fail here rather than at first use.- returns:
The loaded (and, if
modelwas given, validated) lens.
Examples:
# Short model name — no need to remember the HF subpath lens = JacobianLens.from_pretrained("gemma-2-2b", model=model) # HF model ID also works lens = JacobianLens.from_pretrained("google/gemma-2-2b", model=model) # Explicit Hub repo + subpath (backward-compatible) lens = JacobianLens.from_pretrained( "neuronpedia/jacobian-lens", filename="gpt2-small/jlens/Salesforce-wikitext/gpt2_jacobian_lens.pt", model=model, )
- lens_vector_dictionary(model: Any, layer: int) Float[Tensor, 'd_vocab d_model']¶
Full-vocabulary J-lens dictionary at
layer:[d_vocab, d_model].Row
tis the J-lens vectorv_t = J[layer]^T W_U[:, t]– this islens_vectors()over the entire vocabulary. The result is cached while the model’s unembedding is unchanged so a sparse decomposition can reuse it;clear_device_cache()releases it.The dictionary is vocabulary-sized and cached on the model’s device (
d_vocab * d_modelfp32 values, on the order of gigabytes for a large vocabulary), one entry per requested layer. One detached copy ofW_Uis retained per device to detect changes without transferring weights to the host.- Parameters:
model – The model supplying
W_U.layer – Source layer for the dictionary (must be a fitted source layer).
- Returns:
The dictionary, fp32, on the model’s device.
- lens_vectors(model: Any, tokens: str | int | Sequence[str | int], layer: int) Float[Tensor, 'n d_model']¶
Residual-stream directions for vocabulary tokens at a layer.
The J-lens vector for token
tis rowtofW_U J[layer]expressed in layer-layerresidual coordinates:v_t = J[layer]^T W_U[:, t].- Parameters:
model – The model supplying
W_U.tokens – A token string / id, or a sequence of them. Strings must encode to a single token.
layer – Source layer for the vectors.
- Returns:
One vector per token, fp32, on the model’s device.
- classmethod load(path: str) _LensT¶
Load a lens artifact or fit checkpoint saved in a supported schema.
Two file schemas are accepted:
Artifact (the reference format, written by
save()or the Anthropic reference package): must contain aJkey mapping layer indices to transport matrices, plusn_prompts,d_model, and an optionalmetadatadict.Fit checkpoint (running-sum format, written by the reference implementation’s
write_checkpoint()during fitting): must contain ajacobian_sumkey mapping layer indices to running-sum matrices (i.e. the sum over prompts, not yet divided by the prompt count), plusn_done.d_modelis inferred from the first matrix’s shape; no explicitd_modelkey is required or expected. The per-layer means are reconstructed on load. Aconverted_from: "jacobian_lens_checkpoint"key is added to metadata somerge()refuses to silently combine checkpoints with natively TL-fitted lenses. Fit-reserved provenance keys (transformer_lens_fit, etc.) are stripped; scalar fields that can be serialised underweights_only=Trueare preserved. Tensor-valued metadata fields that would fail_validate_metadata()are recorded by name in adropped_fieldslist.Fit checkpoint schema (reference
write_checkpoint()format)¶The reference implementation writes exactly six top-level keys; all other keys in the payload are ignored:
{ "jacobian_sum": {<layer int>: <float32 tensor [d, d]>, ...}, "n_done": <int>, # prompts accumulated into jacobian_sum "next_idx": <int>, # next prompt index (informational) "source_layers": [<int>, ...], # documented layer indices (informational) "target_layer": <int>, # target layer — harvested into metadata "skip_first": <int>, # leading positions skipped (informational) # optional flat provenance accepted from alternative checkpoint writers: "model_name": <str>, "model_revision": <str>, "corpus": <str>, # optional nested provenance accepted from alternative writers: "metadata": {<str>: <scalar/list/dict>, ...}, }
- param path:
Path to the
.ptfile.- raises ValueError:
If the file lacks both a
Jkey (artifact) and ajacobian_sumkey (checkpoint), or if a checkpoint records a non-positiven_prompts.
- classmethod merge(lenses: Sequence[JacobianLens]) JacobianLens¶
Combine lenses fitted on disjoint prompt slices.
The per-layer matrices are averaged weighted by each lens’s
n_prompts, matching the reference implementation, so fitting can be parallelized across processes or machines and merged afterwards. Provenance must match across shards (apart fromn_prompts), so a merge cannot silently relabel matrices fitted with different models, corpora, dtypes, or recorded estimator settings. The merged count replaces the per-shard count.- Parameters:
lenses – Lenses that agree exactly on
source_layersandd_model.- Raises:
ValueError – On an empty sequence, mismatched lenses, or shards from different estimators.
- occupancy(model: Any, activation_or_prompt: Tensor | str, layer: int, *, position: int | None = None, max_atoms: int = 25, num_control_dictionaries: int = 32, seed: int = 0) JSpaceOccupancy¶
Estimate how many J-lens vectors are meaningfully active in an activation at
layer.Resolves
activation_or_prompt(a raw[d_model]vector, or a prompt plusposition) exactly asdecompose(), builds the cached full-vocabulary dictionary vialens_vector_dictionary(), and callsestimate_occupancy().Control dictionaries are
[d_vocab, d_model]CPU draws (for cross-device reproducibility) that dominate run time on an accelerator; lowernum_control_dictionariesfor speed.- Parameters:
model – A raw
TransformerBridge.activation_or_prompt – An activation vector, or a prompt (string / token tensor).
layer – Source layer (must be a fitted source layer).
position – Token position when a prompt is given;
Nonefor a raw activation.max_atoms – Maximum number of J-lens vectors to consider.
num_control_dictionaries – Number of random control dictionaries to average over.
seed – Seed for the random control dictionaries (reproducibility).
- Returns:
A
JSpaceOccupancy.
- readout(model: Any, input: str | Int[Tensor, 'batch seq'], *, layers: Sequence[int] | None = None, positions: Sequence[int] | None = None, use_jacobian: bool = True, top_k: int = 10, return_full_logits: bool = False) JacobianLensReadout¶
Read per-layer vocabulary logits for a prompt.
Runs the model once with caching, transports the residual stream at each requested layer through
J[layer](or the identity whenuse_jacobian=False— the logit lens), and applies the model’s own final norm, unembedding, architecture logit scaling, and logit soft cap.- Parameters:
model – A raw
TransformerBridge.input – A prompt string, or a
[1, seq]token tensor.layers – Layers to read. Defaults to every fitted layer plus the final layer. The final layer (
n_layers - 1) is always read with the identity transport — by construction its lens equals the model’s own output distribution.positions – Token positions to read (negative indices allowed). Defaults to all positions.
use_jacobian – Apply the Jacobian transport.
Falsegives the logit-lens baseline through the identical code path.top_k – Number of values and vocabulary ids retained per layer and position. Defaults to 10.
return_full_logits – Also retain full vocabulary tensors on CPU. This is opt-in because a 64-token Gemma readout across all layers is roughly 1.7 GB.
- Returns:
A
JacobianLensReadout.- Raises:
ValueError – If the model fails
validate_model(),inputis batched,top_kis invalid, a requested layer has no transport matrix, or the model is in training mode.
- save(path: str, *, dtype: dtype = torch.float16) None¶
Save the lens in the reference implementation’s artifact format.
The four official keys (
J,n_prompts,source_layers,d_model) are written unchanged so the file stays loadable by the reference package; TransformerLens provenance is stored under an additivemetadatakey.- Parameters:
path – Destination
.ptpath.dtype – Storage dtype. Defaults to fp16 like the reference implementation — Jacobian entries are order-one, so the smaller dtype costs little precision and halves the artifact on disk.
- property source_layers: List[int]¶
Sorted list of layers this lens has transport matrices for.
- steering_hooks(model: Any, token: str | int, layers: Sequence[int], *, alpha: float = 4.0, positions: Sequence[int] | None = None) List[Tuple[str, Any]]¶
Hooks that steer the residual stream along a token’s J-lens vector.
At each layer the unit-normalized lens vector is added, scaled by
alphatimes the activation’s median per-position residual norm:h <- h + alpha * median||h|| * v̂. This norm-matched parameterization follows the steering description in the reference implementation’s experiment protocols; the paper’s minimal form is the unscaledh <- h + alpha * v_t, recoverable by passing the rawlens_vectors()output to your own hook. The median (not mean) is used so attention-sink positions — whose residual norms run orders of magnitude above typical positions — do not inflate the scale.- Parameters:
model – The model the hooks will run on.
token – The concept token to steer toward.
layers – Layers to intervene at.
alpha – Steering strength scalar;
0disables. Because of the norm-matched scale, values of order 1 already perturb the stream by roughly its own magnitude.positions – Chunk-local positions to steer (negative indices allowed and normalized on every hook invocation). Defaults to all.
- Returns:
[(hook_name, fn), ...]formodel.hooks(fwd_hooks=...)ormodel.run_with_hooks(fwd_hooks=...).
- swap_clamp_hooks(model: Any, source_token: str | int, target_token: str | int, layers: Sequence[int], clean_cache: ActivationCache | Mapping[str, Tensor], *, positions: Sequence[int] | None = None) List[Tuple[str, Any]]¶
Deprecated: use
swap_hooks()withclamp_to=clean_cache.
- swap_hooks(model: Any, source_token: str | int, target_token: str | int, layers: Sequence[int], *, alpha: float = 1.0, positions: Sequence[int] | None = None, clamp_to: ActivationCache | Mapping[str, Tensor] | None = None) List[Tuple[str, Any]]¶
Hooks that exchange two concepts’ coordinates in lens space.
The paper’s patching-in-lens-coordinates intervention: with
V = [v_s, v_t]and lens coordinatesc = V⁺ h(pseudoinverse), the update ish <- h + alpha * V (c_target - c). The component ofhorthogonal tospan{v_s, v_t}is untouched.alpha=2is the paper’s “double-strength” swap.Without
clamp_to,c_target = sigma(c)exchanges the two live coordinates, re-read from the activation seen by every hook. It is therefore an involution when applied repeatedly in a subspace whose coordinates are preserved between layers: a second application can undo the first.With
clamp_to(the paper’s multi-layer clamp protocol),c_targetis the exchange of each layer’s clean-run coordinates, fixed when the hooks are built, so atalpha=1the update is idempotent at each layer:h <- h + V (c_target - V⁺h).- Parameters:
model – The model the hooks will run on.
source_token – The concept to remove (e.g.
" France").target_token – The concept to install (e.g.
" China").layers – Layers to intervene at.
alpha – Swap strength; with
clamp_to, the fraction of the way to the clamped coordinates.positions – Chunk-local positions to swap (negative indices allowed and normalized on every hook invocation, and against the clean activations when clamping). Defaults to all.
clamp_to – Activations from an unmodified
run_with_cacheat each requested layer’sblocks.{layer}.hook_outname. Either theActivationCacheit returns by default or the plain dict fromreturn_cache_object=Falseis accepted.
- Returns:
[(hook_name, fn), ...]formodel.hooks(fwd_hooks=...).
- transport(residual: Float[Tensor, '... d_model'], layer: int) Float[Tensor, '... d_model']¶
Map layer-
layeractivations into the final block’s output basis.Computes
J[layer] @ hper activation vector, in fp32.- Parameters:
residual – Activations from the output of block
layer.layer – Source layer index.
- validate_model(model: Any) JacobianLens¶
Check that
modelmatches this lens; raise loudly if not.Requires a raw causal
TransformerBridgewith the standard direct final-norm/unembed path, verifies recorded model provenance, residual width and layer range, and enforces the published final-block target convention.- Parameters:
model – A raw
TransformerBridge.- Returns:
self, for chaining.- Raises:
TypeError – If model is not a
TransformerBridge.ValueError – On model provenance or
d_modelmismatch, out-of-range source layers, compatibility mode, unsupported attention/output paths, or a non-final target convention.
- class transformer_lens.tools.analysis.LearnedSubspace(d_model: int, rank: int)¶
Bases:
ModuleA trainable rank-
ranksubspace ofd_modelwhose basis stays orthonormal.- Parameters:
rank – Number of basis directions, in
[1, d_model].
- property basis: Float[Tensor, 'd_model rank']¶
- class transformer_lens.tools.analysis.Node(kind: Literal['embed', 'attn_head_out', 'mlp_out', 'q_input', 'k_input', 'v_input', 'mlp_in', 'logits'], position: int, layer: int | None = None, head: int | None = None)¶
Bases:
objectA node in the residual-stream computational graph.
Nodes are the typed, hashable keys the attribution sweep scores. Each node is identified by
(kind, layer, position, head);kindselects the node family and constrains which oflayer/headapply. Three kinds are writers – they contribute a value into the residual stream:"embed": the token embedding write.layerandheadareNone."attn_head_out": one attention head’s output.layerandheadset."mlp_out": one layer’s MLP output.layerset,headisNone.
Five kinds are readers – they consume the residual stream as an edge’s destination (see
enumerate_edges()):"q_input"/"k_input"/"v_input": one attention head’s split Q/K/V input.layerandheadset."mlp_in": one layer’s MLP entry.layerset,headisNone."logits": the terminal readout of the final residual, read atblocks.{n_layers-1}.hook_resid_post.layeris that final layer andheadisNone. Every writer feeds this reader, so a writer’s aggregate over its outgoing edges equals its direct node score.
positionis the sequence index the node is read at. The invariants above are enforced in__post_init__so a malformed key raises rather than silently producing a wrong graph.- head: int | None = None¶
- property hook_name: str¶
The cache hook point this node reads from.
Uses the standard
TransformerBridgealias names (hook_embed,blocks.{l}.attn.hook_z,blocks.{l}.hook_mlp_out,blocks.{l}.attn.hook_q_input/hook_k_input/hook_v_input,blocks.{l}.hook_mlp_in,blocks.{l}.hook_resid_post); the per-head nodes (attn_head_out,q_input,k_input,v_input) slice headself.headout of the shared per-head tensor.
- kind: Literal['embed', 'attn_head_out', 'mlp_out', 'q_input', 'k_input', 'v_input', 'mlp_in', 'logits']¶
- layer: int | None = None¶
- position: int¶
- class transformer_lens.tools.analysis.NormMatchedPlacebo(reference: SubspaceInterchange, basis: Tensor)¶
Bases:
objectMove each base exactly as far as
referencedoes, but inside a random subspace.An effect that the placebo also produces comes from displacing the activation by that much, not from the aligned subspace.
- reference¶
The intervention whose displacement is matched.
- basis¶
Orthonormal basis of the placebo subspace, usually from
random_basis()with the reference’s rank, or fromrandom_neuron_basis()for a reference built byneuron_basis().- Type:
torch.Tensor
- basis: Tensor¶
- reference: SubspaceInterchange¶
- exception transformer_lens.tools.analysis.SparseProbeConvergenceError¶
Bases:
RuntimeErrorA probe fit failed to converge or produced non-finite output.
Distinct from other ``RuntimeError``s so the sweep’s control-rejection path swallows only convergence failures, never unrelated runtime faults.
- class transformer_lens.tools.analysis.SubspaceBasis(basis: Float[Tensor, 'ambient rank'], singular_values: Float[Tensor, 'spectrum'], rank: int, measured_rank: int, rtol: float, threshold: float, input_shape: Tuple[int, int])¶
Bases:
objectAn explicitly ranked orthonormal basis extracted from a matrix.
- basis¶
Orthonormal column-space basis,
[ambient_dim, rank].- Type:
jaxtyping.Float[Tensor, ‘ambient rank’]
- singular_values¶
All reduced-SVD singular values, in descending order.
- Type:
jaxtyping.Float[Tensor, ‘spectrum’]
- rank¶
Number of retained basis directions.
- Type:
int
- measured_rank¶
Numerical rank before optional caller truncation.
- Type:
int
- rtol¶
Effective relative rank tolerance.
- Type:
float
- threshold¶
Absolute singular-value threshold used for rank measurement.
- Type:
float
- input_shape¶
Shape of the matrix from which the basis was extracted.
- Type:
Tuple[int, int]
- property ambient_dim: int¶
Dimension of the space containing the subspace.
- basis: Float[Tensor, 'ambient rank']¶
- input_shape: Tuple[int, int]¶
- measured_rank: int¶
- rank: int¶
- rtol: float¶
- singular_values: Float[Tensor, 'spectrum']¶
- threshold: float¶
- class transformer_lens.tools.analysis.SubspaceInterchange(basis: Tensor | LearnedSubspace, strength: float = 1.0)¶
Bases:
objectSet the base’s coordinates inside
basisto the source’s.- basis¶
Orthonormal basis,
[d_model, rank], or aLearnedSubspace.- Type:
torch.Tensor | transformer_lens.tools.analysis.interchange.LearnedSubspace
- strength¶
1 interchanges the coordinates; other values scale the move, 0 leaves the base.
- Type:
float
- basis: Tensor | LearnedSubspace¶
- strength: float = 1.0¶
- transformer_lens.tools.analysis.arbitrary_targets(keys: Sequence[Hashable], n_classes: int, seed: int) Int[Tensor, 'batch']¶
A fixed pseudo-random class per key: targets for the arbitrary-label control.
Train
fit_das()on these instead of the high-level model’s targets, with the same pairs, rank and budget. The interchange accuracy it reaches shows how much accuracy the method’s expressivity alone produces; a learned subspace should clearly exceed it.- Parameters:
keys – One key per pair identifying its source, e.g. the source text.
- Returns:
A class in
[0, n_classes)per key; equal keys always get equal classes.
- transformer_lens.tools.analysis.attention_head_subspace_affinity(model: Any, *, source_role: str = 'O', target_role: str, layer_order: str = 'forward', rank: int | None = None, rtol: float | None = None) HeadAffinityResult¶
Compute OQ, OK, or OV Projection Kernel affinities for a TransformerBridge.
K/V axes preserve native key-value heads on grouped-query attention models; they are never expanded to query-head count. Hybrid models include only attention blocks and report their original block indices.
- Parameters:
model – A TransformerBridge exposing readable per-head attention weights.
source_role – Source role; v1 supports only
"O".target_role – One of
"Q","K", or"V".layer_order –
"forward"keeps strict earlier-to-later pairs;"all"keeps every pair.rank – Optional common truncation rank. By default every head must be full column rank.
rtol – Optional relative numerical-rank tolerance.
- Returns:
Affinity tensors, validity mask, original layer indices, and rank metadata.
- transformer_lens.tools.analysis.attribution_patch(model: Any, clean: Tensor, corrupt: Tensor, metric_fn: Callable[[Tensor], Tensor], config: EdgeAttributionConfig = EdgeAttributionConfig(granularity='node', ig_steps=1)) AttributionResult¶
Estimate every component’s causal effect on
metric_fnin two forwards + one backward.For each clean/corrupt pair this runs a clean forward (for
a_clean) and a corrupt forward whose backward hooks captureg = d(metric)/d(a)(fora_corruptand its gradient). At node granularity (config.granularity == "node") each node is scored with the first-order Taylor estimateeffect(node) = (a_clean - a_corrupt) . g. At edge granularity (config.granularity == "edge") each writer -> reader edge is scored witheffect(edge) = (a_clean[writer] - a_corrupt[writer]) . d(metric)/d(input of reader), andnode_scoresholds each writer’s aggregate effect (the sum of its outgoing edge scores).Sign/direction convention (denoising form): gradients are taken on the corrupt run and the estimate points toward the clean activation, so a positive score means patching that node from corrupt toward clean moves the metric in the positive direction. An oracle-parity test maps this convention onto a pinned reference rather than assuming the two agree.
Dataset averaging:
clean/corruptmay hold a batch of prompt pairs. Each pair is scored independently (per-example forward/backward, so its own reconstruction identity holds) and per-node (or per-edge) scores are averaged across the batch before ranking.The model and every submodule must be in evaluation mode. Separate clean and corrupt forwards cannot produce meaningful activation differences if stochastic training layers such as dropout remain active.
- Parameters:
model – A
TransformerBridge(or compatible) exposingcfg.n_layers,hook_dict, andhooks().clean – Clean token ids, shape
[batch, seq].corrupt – Corrupt token ids, shape
[batch, seq], paired row-by-row withclean.metric_fn – Maps single-example logits to a scalar to differentiate.
config – Sweep configuration. Node and edge granularity are both supported with plain attribution (
ig_steps=1);ig_steps>1raises at construction.
- Returns:
An
AttributionResultwhosenode_scoresare averaged over the batch. For an edge-granularity sweep,edge_scoresis populated too andnode_scoresis the per-writer aggregate of those edge scores. The graph’s terminal logits reader gives every writer an edge carrying its direct skip-connection contribution to the metric, so this aggregate equals the quantity a node-granularity sweep on the same model returns (including for the final layer’s MLP output, whose only outgoing edge is the one to the logits reader).- Raises:
ValueError – if
clean/corruptare not 2D, hold a different number of pairs, a pair tokenizes to different lengths (activations must align position-by-position), or the model or one of its submodules is in training mode. At edge granularity, also if per-head attention outputs are normalized or scaled before the residual add (post-norm, scaled-residual or parallel-mixer blocks), whereattn.hook_resultis not a head’s residual contribution, or if an attention layer’s K/V head count differs fromn_heads(GQA/MQA).
- transformer_lens.tools.analysis.collect_activations(model: Any, hook_name: str, inputs: Tensor, task_logits: Callable[[Tensor], Float[Tensor, 'batch n_classes']], *, positions: Int[Tensor, 'batch'] | None = None, batch_size: int = 256) Float[Tensor, 'batch d_model']¶
Activations at
hook_name, at one position per example if given, returned on the CPU.- Parameters:
model – A model exposing the hook API.
inputs – Model inputs, one row per example.
task_logits – Runs the model on a batch of inputs.
positions – For
[batch, pos, d_model]activations, the position to read per example.batch_size – Rows per forward pass.
- Returns:
Activations,
[batch, d_model].- Raises:
ValueError – If any part of the model is in training mode, or the activation does not match the positions given (or not given).
RuntimeError – If the hook does not fire exactly once per forward pass.
- transformer_lens.tools.analysis.direct_logit_attribution(model, input: str | List[str] | Tensor | None = None, answer_tokens: str | int | Tensor | None = None, incorrect_tokens: str | int | Tensor | None = None, *, unit: str = 'component', pos: int | integer | Tuple[int] | Tuple[int, int] | Tuple[int, int, int] | List[int] | Tensor | ndarray | None = -1, cache: ActivationCache | None = None) DirectLogitAttribution¶
Compute Direct Logit Attribution for a prompt.
Decomposes the contribution of model components to the logit of
answer_tokens(or, ifincorrect_tokensis given, to the logit differenceanswer - incorrectalong theW_Udirection, which is usually what you want for circuit analysis).The model is run once with caching unless a precomputed
cacheis passed.Note that DLA attributes only the part of a logit that comes from the residual stream through the unembedding direction; the unembedding bias
b_Uis a per-token constant that no component produces. So a complete decomposition reconstructslogit[token] - b_U[token]rather than the raw logit.On a
TransformerBridge, compatibility mode must be enabled and the final normalization’s affine parameters must be folded intoW_Uandb_U(or already be identity); otherwise the projection direction is wrong and DLA would return silently incorrect numbers. Hybrid architectures (Mamba/SSM/Mixer/LinearAttention) are not yet supported becausedecompose_residonly understands theattn_out + mlp_outblock layout; both conditions raise an explicit error at call time, as does a Bridge whose readout is notln_final -> unembedon the last block’s output; a prompt run here is also checked against the model’s own output, a precomputedcacheonly structurally.- Parameters:
model – A
TransformerBridgewithenable_compatibility_mode()already called and an identity final normalization.input – Prompt to run — a string, list of strings, or token tensor. Optional only when a precomputed
cacheis supplied.answer_tokens – The correct token(s) to attribute, as a string, id, or tensor. A string is converted with
model.to_single_token.incorrect_tokens – Optional baseline token(s). When given, attribution is computed for the
answer - incorrectresidual direction. Must broadcast to the same shape asanswer_tokens.unit –
Decomposition granularity:
"component"(default): embedding + each layer’s attention and MLP output (viadecompose_resid)."layer": cumulative residual stream after each sublayer, i.e. logit-lens trajectory (viaaccumulated_resid)."head": each attention head individually, plus a remainder term for everything else (viastack_head_results).
pos – Sequence position(s) to attribute. Defaults to
-1(the final token, the usual choice for next-token DLA). PassNoneto keep every position (the result then has a trailing position axis).cache – Optional precomputed
ActivationCacheto reuse instead of running the model again.
- Returns:
A
DirectLogitAttributionwithattribution(shape[component, *batch_and_pos]) and alignedlabels.- Raises:
ValueError – If
unitis invalid,answer_tokensisNone, neitherinputnorcacheis provided, or aTransformerBridgeis passed without compatibility mode enabled, with an active learned final-norm weight or bias, or with a readout that is notln_final -> unembed; also if the model must run while any module is in training mode (a suppliedcacheis not checked).NotImplementedError – If a
TransformerBridgereports a hybrid block layout (Mamba/SSM/Mixer/LinearAttention).
- transformer_lens.tools.analysis.faithfulness(model: Any, clean: Tensor, corrupt: Tensor, metric_fn: Callable[[Tensor], Tensor], circuit: Sequence[tuple[Node, Node]] | Sequence[tuple[Node, Node, float]], config: FaithfulnessConfig = FaithfulnessConfig(ablation='corrupt'), *, mean_tokens: Tensor | None = None) FaithfulnessResult¶
Measure how much of the clean-to-corrupt metric gap a circuit recovers.
Ablates every edge outside
circuit(forward-only, exact rather than linearized) and reports the metric the model then produces. Feed a ranked edge set straight in fromattribution_patch(..., config=EdgeAttributionConfig(granularity="edge")).top_edges(k=...).Under mean ablation recovery is still normalized to the clean/corrupt gap, so an empty circuit need not have zero recovery.
- Parameters:
model – A
TransformerBridge(or compatible) exposingcfg.n_layers,hook_dict, andhooks().clean – Clean token ids for one evaluated example, shape
[1, seq].corrupt – Paired corrupt token ids, shape
[1, seq].metric_fn – Maps single-example logits to a scalar.
circuit – The edges to keep, as
(writer, reader)pairs or the(writer, reader, score)triplestop_edgesreturns. Every other edge in the graph is ablated. Duplicate entries count once.config – Ablation configuration. Defaults to replacing an ablated writer with the corrupt run’s own contribution.
mean_tokens – Required only for
ablation="mean". Held-outint32/int64calibration token ids,[n_calibration, seq]at the evaluated length and on the clean/corrupt device; writer activations are averaged per position and head. Rows equal to either endpoint are rejected; avoid semantic leakage too.
- Returns:
A
FaithfulnessResult. The per-edge-class breakout costs one extra forward per retained class.- Raises:
ValueError – if
clean/corruptare not 2D, hold a different number of pairs, hold more than one pair, a pair tokenizes to different lengths, the model or a submodule is in training mode, a circuit edge is not in the graph, the clean and corrupt metrics are equal (so the recovered fraction is undefined), mean calibration is missing, empty, misaligned, on a different input device, has an unsupported dtype, contains an evaluated endpoint, or is supplied in corrupt mode; or per-head attention outputs are normalized or scaled before the residual add (post-norm, scaled-residual or parallel-mixer blocks), or an attention layer’s K/V head count differs fromn_heads(GQA/MQA).
- transformer_lens.tools.analysis.fit_das(model: Any, hook_name: str, base_inputs: Tensor, source_inputs: Tensor, targets: Int[Tensor, 'batch'], task_logits: Callable[[Tensor], Float[Tensor, 'batch n_classes']], *, rank: int, base_positions: Int[Tensor, 'batch'] | None = None, source_positions: Int[Tensor, 'batch'] | None = None, epochs: int = 20, batch_size: int = 128, lr: float = 0.01, strength: float = 1.0, seed: int = 0, device: str | device | None = None, micro_batch_size: int | None = None) DASResult¶
Learn the subspace whose interchange makes the model output
targets(DAS).targets[i]is the class the high-level causal model predicts for baseiwith the aligned variable set to its value in sourcei. The basis is trained with cross-entropy on the task logits under the interchange. Model parameters are frozen during the call and theirrequires_gradflags restored afterwards.Train on pairs where several variables differ between base and source, labelled by the high-level model’s interchange, as well as on pairs that differ only in the aligned variable: otherwise the subspace can learn whatever the pairs happen to move together.
- Parameters:
model – A model exposing the hook API.
hook_name – The hook point to align.
base_inputs – Base inputs, one row per pair.
source_inputs – Source inputs, one row per pair.
targets – The high-level model’s output class for each pair under the interchange.
task_logits – Runs the model on a batch of inputs and returns task logits.
rank – Dimension of the subspace.
base_positions – For
[batch, pos, d_model]activations, the base position per pair.source_positions – Likewise for the sources.
epochs – Passes over the pairs.
batch_size – Pairs per optimisation step.
lr – Adam learning rate.
strength – Interchange strength during training.
seed – Seed for the basis initialisation and the batch order.
device – Device for the subspace’s parameters; by default the device of the model’s parameters, or the CPU for a model without any.
micro_batch_size – Split each batch into parts this size and accumulate gradients: the same gradients, up to floating-point rounding, in less memory.
- Returns:
The learned subspace with its training losses.
- Raises:
ValueError – If any part of the model is in training mode, or the inputs and targets differ in length.
- transformer_lens.tools.analysis.fit_sparse_probe(features: Float[Tensor, 'example feature'], labels: Bool[Tensor, 'example'] | Integer[Tensor, 'example'], *, k: int, test_fraction: int | float = 0.3, positive_label: int | bool = 1, groups: Integer[Tensor, 'example'] | None = None, preprocess: str = 'none', std_floor: int | float = 0.001, class_weight: str | None = 'balanced', l2_strength: int | float = 0.01, seed: int = 0, max_iter: int = 200, max_refinement_steps: int = 25, decrement_tolerance: int | float = 1e-12) SparseProbeResult¶
Fit a train-only-selected k-sparse binary logistic probe.
The stratified split is created before feature scoring or optional standardization. Floating result tensors are detached CPU float64 tensors.
- Parameters:
features – Finite float16/bfloat16/float32/float64 tensor shaped
[example, feature].labels – Boolean or integer binary labels shaped
[example].k – Number of coordinates selected by absolute train class-mean difference.
test_fraction – Requested held-out fraction within each class. With
groupsit targets held-out rows per class, which whole groups only approximate.positive_label – Label defining the positive class and score sign.
groups – Optional integer group IDs; each group is held out whole, with both classes on both sides. Groups may mix classes, but each class must appear in two or more.
preprocess –
"none"or train-only"standardize".std_floor – Lower bound on a non-constant column’s
"standardize"scale, so a near-constant column is not amplified to unit scale;0disables it.class_weight –
"balanced"orNonefor unweighted BCE.l2_strength – Positive coefficient penalty in the logistic objective.
seed – Local CPU-generator seed used only for the stratified split.
max_iter – Maximum LBFGS iterations before Newton refinement. LBFGS also stops once its function evaluations reach
max_iter * 5 // 4(stop_reason="max_eval"; the line search can finish one past it), a budget equal tomax_iterwhenmax_iter <= 3.max_refinement_steps – Maximum damped Newton steps after LBFGS; zero only checks.
decrement_tolerance – Largest accepted Newton decrement
g^T H^-1 g / 2, an estimate of the objective gap to the optimum in nats; a larger gap raises.
- Returns:
Selected support, fitted parameters, split/preprocessing metadata, metrics, and optimizer diagnostics.
- Raises:
ValueError – If inputs, groups, or options violate the binary-probe contract.
SparseProbeConvergenceError – If the optimizer fails or misses its convergence threshold.
- transformer_lens.tools.analysis.get_act_patch_direct_path(model: TransformerLensModel, corrupted_tokens: Tensor, clean_cache: ActivationCache, corrupted_cache: ActivationCache, patching_metric: Callable[[Tensor], Tensor], src_layer: int, src_head: int, component: Literal['q', 'k', 'v'] = 'q', verbose: bool = True) Float[Tensor, 'n_layers n_heads']¶
Patch one source head’s output into each later head’s Q, K or V input alone.
Direct path patching (Wang et al. 2022) isolates the edge A -> B: A’s clean-minus-corrupted write (
z @ W_O) is added at every position to B’s own pre-ln1copy of the residual, while every other reader still sees A’s corrupted output. The result is the exact edge intervention, folded LayerNorm or not.The sweep temporarily enables
cfg.use_split_qkv_input(restoring the caller’s flags on exit), which costs about3 * n_headstimes the usualln1activation memory per forward.- Parameters:
model – A
TransformerBridgewhose attention exposes the pre-Q/K/V fork.corrupted_tokens – Token ids for the corrupted run,
[batch, pos].clean_cache – Cache of the clean run; must hold
blocks.{src_layer}.attn.hook_z.corrupted_cache – Cache of the corrupted run; must hold the same
hook_z.patching_metric – Maps the patched logits to a scalar.
src_layer – Layer of the source head.
src_head – Index of the source head.
component – Destination input to patch:
"q"(default),"k"or"v".
- Returns:
results[l, h]is the metric with the path into head(l, h)patched. Rowsl <= src_layerare 0.0 placeholders, not measurements.- Return type:
[n_layers, n_heads]- Raises:
ValueError – if a block from
src_layeron has no attention, if the source block normalises, scales or joins its attention output before the residual add (post-norm, scaled-residual or parallel-mixer blocks), ifcomponentis"k"or"v"on a GQA/MQA model, or if any module is in training mode.NotImplementedError – if a destination layer’s attention has no pre-Q/K/V fork.
- transformer_lens.tools.analysis.get_act_patch_direct_path_all_sources(model: TransformerLensModel, corrupted_tokens: Tensor, clean_cache: ActivationCache, corrupted_cache: ActivationCache, patching_metric: Callable[[Tensor], Tensor], component: Literal['q', 'k', 'v'] = 'q', verbose: bool = True) Float[Tensor, 'n_layers n_heads n_layers n_heads']¶
Run
get_act_patch_direct_path()from every source head.results[sl, sh, dl, dh]is the metric with the path from head(sl, sh)into head(dl, dh)patched, and 0.0 wheredl <= sl. One forward per (source, later destination) pair, so it suits small models or targeted sub-sweeps.
- transformer_lens.tools.analysis.get_sparse_decomposition(x: Tensor, dictionary: Tensor, k: int = 25, *, algorithm: str = 'nonnegative_orthogonal_matching_pursuit') JSpaceDecomposition¶
Greedily decompose
xinto ak-sparse nonnegative combination of atoms.- Parameters:
x – Target vector, shape
[d_model].dictionary – Atom matrix, shape
[num_atoms, d_model](rows are atoms).k – Upper bound on the number of atoms to select. Selection stops early once no unselected atom is materially positively correlated with the residual, so fewer than
katoms may be selected (and fewer still may be numerically active).algorithm – Coefficient-update rule.
"nonnegative_orthogonal_matching_pursuit"(default) re-solves the selected-set coefficients exactly as a nonnegative least-squares fit;"gradient_pursuit"takes a single projected-gradient step per atom. See the module docstring for the trade-off (they use the same selection rule, while the exact re-solve is optimal on each selected set).
- Returns:
A
JSpaceDecomposition. Itssupportholds only the numerically active atoms andselected_supportevery selected atom, withsupport.numel() <= selected_support.numel() <= k.- Raises:
ValueError – On an unknown
algorithm, complex or non-finite inputs, a non-2-D dictionary, a target whose length does not matchd_model,koutside[1, num_atoms], or a dictionary with non-finite or zero-norm atoms.RuntimeError – If
algorithm="nonnegative_orthogonal_matching_pursuit"and the nonnegative least-squares solve cannot be certified against its KKT conditions within its numerical tolerance.
- transformer_lens.tools.analysis.intervened_logits(model: Any, hook_name: str, intervention: Callable[[Tensor, Tensor], Tensor], base_inputs: Tensor, source_activations: Float[Tensor, 'batch d_model'], task_logits: Callable[[Tensor], Float[Tensor, 'batch n_classes']], *, positions: Int[Tensor, 'batch'] | None = None, batch_size: int = 256) Float[Tensor, 'batch n_classes']¶
Task logits under
intervention, in batches without gradients, returned on the CPU.The evaluation counterpart of
run_with_intervention(), with the same arguments and checks: memory is bounded bybatch_sizerather than by the number of pairs.- Parameters:
model – A model exposing the hook API.
intervention – Maps base and source activations to new base activations.
source_activations – Activations from the source inputs at the same hook point, one row per base.
task_logits – Runs the model on a batch of inputs.
positions – For
[batch, pos, d_model]activations, the position to intervene on per base.batch_size – Rows per forward pass.
- Returns:
Task logits under the intervention,
[batch, n_classes].- Raises:
ValueError – If any part of the model is in training mode, or the inputs do not pair up.
- transformer_lens.tools.analysis.logit_lens(model: Any | ActivationCache, input: str | List[str] | Tensor | None = None, *, cache: ActivationCache | None = None, layers: Sequence[int] | None = None, incl_mid: bool = False, positions: int | integer | Tuple[int] | Tuple[int, int] | Tuple[int, int, int] | List[int] | Tensor | ndarray | None = -1, batch_slice: int | integer | Tuple[int] | Tuple[int, int] | Tuple[int, int, int] | List[int] | Tensor | ndarray | None = None, lens: Callable[[Tensor, int], Tensor] | None = None, apply_ln: bool = True, vocab: Sequence[int] | Tensor | None = None, targets: str | int | Sequence[str | int] | Tensor | None = None, return_type: str = 'logits', top_k: int | None = None, chunk_size: int = 64, enable_grad: bool = False) LogitLensResult¶
Read the accumulated residual stream through the final norm and unembedding.
Builds the stack with
accumulated_resid(), optionally applies a per-entrylenstranslator, applies the final norm throughapply_ln_to_stack()with recomputed statistics, and hands the result tologit_readout(). The final stack entry reproduces the model’s logits (raw bridge) or log-probabilities (compatibility mode). Bridges whose readout is notln_final -> unembedon the last block’s output are refused; a prompt run here withapply_ln=Trueis also checked against the model’s own output, a suppliedcacheonly structurally.- Parameters:
model – A
TransformerBridge, or anActivationCache(theninputmust be omitted).input – Prompt(s) or token tensor to run when no
cacheis given. Only the residual-stream hooks are cached. A batch of strings is padded by the tokenizer, so with the defaultpositions=-1the shorter prompts are read at a pad position; pass a token tensor (or per-prompt positions) when prompts differ in length.cache – An existing cache to read instead of running the model.
layers – Indices into the accumulated stack (negative allowed);
Nonekeeps every entry.incl_mid – Include
resid_midentries. Raises on hybrid stacks whose SSM blocks have noresid_mid.positions – Position selection (
Slicesemantics); default last token.batch_slice – Batch selection (
Slicesemantics).lens – Optional
f(entry, index) -> entryapplied to each stack entry before the norm, e.g. a tuned-lens translator. Combine withenable_grad=Trueto fit or attribute through it.targets – As in
logit_readout(); a per-row tensor is aligned with the stack’s[batch, pos]dims afterpositionsandbatch_sliceare applied ([batch, pos]next-token ids withpositions=None,[batch]with the default last position).apply_ln – As in
logit_readout().vocab – As in
logit_readout().return_type – As in
logit_readout().top_k – As in
logit_readout().chunk_size – As in
logit_readout().enable_grad – As in
logit_readout().
- Returns:
A
LogitLensResult.
- transformer_lens.tools.analysis.logit_readout(model: Any, vectors: Float[Tensor, '... d_model'], *, apply_ln: bool = True, vocab: Sequence[int] | Tensor | None = None, targets: str | int | Sequence[str | int] | Tensor | None = None, return_type: str = 'logits', top_k: int | None = None, chunk_size: int = 64, enable_grad: bool = False) LogitReadout¶
Read
d_modelvectors through the model’s final norm and unembedding.Computes
transform(ln_final(x) @ W_U + b_U)for every vector, wheretransformis the adapter’s post-unembedding transform, in chunks ofchunk_sizerows so at mostchunk_size × d_vocablogits exist at once. Everything derived from the full vocabulary (the softmax normalizer,entropy,target_ranks) is computed per chunk and discarded; only the selected columns are kept.- Parameters:
model – A
TransformerBridgein eval mode.vectors – Residual-stream-shaped vectors, any leading dims.
apply_ln – Apply the model’s
ln_finalmodule first (recomputed statistics per vector).Falsereads the raw vectors and does not reproduce the model.vocab – Token ids to keep along the trailing axis.
targets – Tokens whose values and full-vocabulary ranks to report. Strings (single tokens) or ints, or a sequence of them, are shared across every row. A tensor is per row: it is right-aligned and broadcast to the vectors’ leading dims (for
[batch, pos, d_model]vectors pass[batch, pos]next-token ids, or[batch, 1]for one id per example) and the trailing axis ofvalueshas length 1. Note the convention differs fromActivationCache.logit_attrs, which reads a 1-D tensor as per-example first; here alignment is purely right-to-left.return_type –
"logits","log_probs"or"probs".top_k – Keep the
klargest-logit tokens per vector, with their ids.chunk_size – Rows of
vectorsprocessed per unembedding matmul.enable_grad – Keep autograd on (for trainable lenses and attribution); default runs under
torch.no_grad().
- Returns:
A
LogitReadout.- Raises:
ValueError – On a bad
return_type, more than one selector, achunk_sizebelow 1, a wrong trailing dimension, empty vectors, per-row targets that do not broadcast, a model whose final norm cannot be applied exactly, or a bridge whose readout is notln_final -> unembedon the last block’s output.NotImplementedError – For encoder-decoder and encoder-only bridges.
- transformer_lens.tools.analysis.mean_difference_basis(activations: Float[Tensor, 'batch d_model'], labels: Sequence[Hashable]) Float[Tensor, 'd_model rank']¶
The span of the centred class means: for two classes, the difference-in-means direction.
- Parameters:
activations – Activations, one row per example.
labels – The variable’s value for each example; at least two distinct values.
- Returns:
Orthonormal basis of rank
n_classes - 1,[d_model, n_classes - 1].- Raises:
ValueError – If fewer than two classes are present.
- transformer_lens.tools.analysis.neuron_basis(d_mlp: int, neurons: Sequence[int] | ndarray | Tensor) Float[Tensor, 'd_mlp k']¶
The coordinate basis of a set of MLP neurons, e.g. the features a sparse probe selects.
Interchanging it sets exactly those neurons to the source’s values, at a neuron hook such as
blocks.N.mlp.hook_post. Compare it withrandom_neuron_basis()of the same size: a random direction is the wrong placebo for a claim about neurons, because it spreads over every neuron.- Parameters:
d_mlp – Number of neurons at the hook.
neurons – Integer indices of the neurons, each in
[0, d_mlp)and none repeated.
- Returns:
Orthonormal basis of unit vectors,
[d_mlp, k], in the order given.- Raises:
ValueError – If no neuron is given, or an index is not an integer, out of range or repeated.
- transformer_lens.tools.analysis.orthonormal_subspace(matrix: Float[Tensor, 'ambient width'], *, rank: int | None = None, rtol: float | None = None) SubspaceBasis¶
Extract an explicitly ranked orthonormal column-space basis.
Low-precision inputs are promoted to float32 before the reduced SVD. With no explicit
rtol, numerical rank uses the compute-SVD error scale relative to the largest singular value, so the default does not depend on the storage dtype — e.g. a 4096-row half-precision input gets4096 * float32_eps(about4.9e-4), tight enough to flag an exactly repeated column as rank-deficient. An explicitranktruncates the measured subspace but may not exceed its measured rank.- Parameters:
matrix – Finite floating-point matrix with shape
[ambient_dim, width].rank – Optional number of leading singular directions to retain.
rtol – Optional non-negative relative singular-value threshold.
- Returns:
Basis, complete singular spectrum, and rank metadata.
- Raises:
ValueError – If the matrix or rank policy is invalid.
- transformer_lens.tools.analysis.probe_basis(weights: Float[Tensor, 'n_rows d_model']) Float[Tensor, 'd_model rank']¶
The directions of a linear probe’s weights, in activation space.
Undo any input scaling first: for a probe fit on standardised inputs, divide each weight by its feature’s standard deviation.
- Parameters:
weights – Probe weights; one row for a binary probe, one row per class otherwise.
- Returns:
the weight direction for one row, the span of the centred rows (rank
n_rows - 1) for several.- Return type:
Orthonormal basis
- transformer_lens.tools.analysis.projection_kernel(subspace_a: SubspaceBasis, subspace_b: SubspaceBasis, *, check_orthonormal: bool = True) ProjectionKernelResult¶
Measure overlap between two explicitly extracted subspaces.
Raw PK lies in
[0, min(rank_a, rank_b)]. The normalized value isPK / sqrt(rank_a * rank_b), the cosine between the two projection matrices. Principal angles are returned in radians.
- transformer_lens.tools.analysis.random_basis(d_model: int, rank: int, seed: int) Float[Tensor, 'd_model rank']¶
A seeded random orthonormal basis: the baseline any aligned basis should beat.
- Parameters:
seed – Seed for the Gaussian matrix the basis is drawn from.
- Returns:
Orthonormal basis,
[d_model, rank].
- transformer_lens.tools.analysis.random_init_bridge(model_name: str, *, seed: int, dtype: dtype = torch.float32, device: str | device | None = None, **boot_kwargs: Any) Any¶
A
TransformerBridgewith the architecture’s HuggingFace initialisation and no training.The random-init control: train
fit_das()on it with the same pairs, rank and budget as on the trained model. Effects DAS finds here come from the method and the architecture, not from anything the model learned. Built withload_weights=False, so the model class and prepared configuration match the trained bridge.- Parameters:
model_name – Model name or alias, as for
TransformerBridge.boot_transformers.device – Device for the bridge; by default the device
boot_transformerswould choose.**boot_kwargs – Passed on to
TransformerBridge.boot_transformers, e.g.revision.
- Returns:
The untrained
TransformerBridge, in evaluation mode.
- transformer_lens.tools.analysis.random_neuron_basis(d_mlp: int, k: int, seed: int, exclude: Sequence[int] | ndarray | Tensor | None = None) Float[Tensor, 'd_mlp k']¶
The coordinate basis of
kneurons drawn at random: the placebo forneuron_basis().- Parameters:
d_mlp – Number of neurons at the hook.
seed – Seed for the draw; the caller’s random stream is untouched.
exclude – Neurons the draw must avoid, usually the ones the placebo is compared with.
- Returns:
Orthonormal basis of unit vectors,
[d_mlp, k].- Raises:
ValueError – If fewer than
kneurons remain to draw from, orexcludeholds an invalid index.
- transformer_lens.tools.analysis.random_projection_kernel_moments(ambient_dim: int, rank: int) RandomSubspaceReference¶
Return PK moments for independent Haar-distributed rank-
rankplanes.These idealized descriptive moments are not calibrated p-values for trained model weights, whose head subspaces are dependent and anisotropic.
- transformer_lens.tools.analysis.reinitialized(model: Module, seed: int) Module¶
A copy of
modelwith freshly initialised parameters: the random-init control.For models built from standard
nnlayers, such as aHookedRootModule: every module withreset_parametersis reset, so every parameter must belong to one. Buffers, such as fixed architectural matrices, are kept. For HuggingFace models userandom_init_bridge(), which applies the architecture’s own initialisation scheme.- Parameters:
model – The trained model; it is not modified.
- Returns:
The untrained copy, on the device of the model’s parameters, in evaluation mode.
- Raises:
ValueError – If a parameter belongs to no module with
reset_parameters, so it would keep its trained value.
- transformer_lens.tools.analysis.run_with_intervention(model: Any, hook_name: str, intervention: Callable[[Tensor, Tensor], Tensor], base_inputs: Tensor, source_activations: Float[Tensor, 'batch d_model'], task_logits: Callable[[Tensor], Float[Tensor, 'batch n_classes']], *, positions: Int[Tensor, 'batch'] | None = None) Float[Tensor, 'batch n_classes']¶
Task logits for
base_inputswithinterventionapplied athook_name, in one pass.Differentiable with respect to any parameters of
intervention, for training an intervention. To evaluate one over many pairs in bounded memory, useintervened_logits().- Parameters:
model – A model exposing the hook API.
intervention – Maps base and source activations to new base activations, e.g. a
SubspaceInterchange.source_activations – Activations from the source inputs at the same hook point, one row per base, e.g. from
collect_activations().task_logits – Runs the model on a batch of inputs.
positions – For
[batch, pos, d_model]activations, the position to intervene on per base.
- Returns:
Task logits under the intervention.
- Raises:
ValueError – If the activation does not match the positions given (or not given).
RuntimeError – If the hook does not fire exactly once in the forward pass.
- transformer_lens.tools.analysis.solve_coordinate_patch(x: Tensor, dictionary: Tensor, source_idx: int, target_idx: int, *, decomposition: JSpaceDecomposition | None = None, k: int = 25, mode: str = 'substitute', alpha: float = 1.0, algorithm: str = 'nonnegative_orthogonal_matching_pursuit') CoordinatePatch¶
Edit one sparse J-space coordinate while preserving its recovered frame.
substitutezeros the source and replaces the target coordinate with the source value;swapexchanges the two values. An absent target is appended at zero. The edit is blended byalphaand reconstructed over the original residualx - reconstruction.- Parameters:
x – Activation vector with shape
[d_model].dictionary – Atom matrix with shape
[num_atoms, d_model]; rows are atoms.source_idx – Atom index that must occur in the decomposition’s active support.
target_idx – Distinct atom index to receive or exchange the source coordinate.
decomposition – Optional decomposition of
xunderdictionary. Reuse validates only the selected and edited rows, avoiding another full-dictionary scan.k – Sparse-solver upper bound when no decomposition is supplied.
mode –
"substitute"to overwrite the target, or"swap"to exchange coordinates.alpha – Finite interpolation strength. Zero returns an unchanged float32 clone.
algorithm – Sparse coefficient-update rule when no decomposition is supplied. A supplied decomposition is accepted if it fits as either algorithm’s output.
- Returns:
A
CoordinatePatchwith the anchored edit and numerical diagnostics.- Raises:
ValueError – If tensors, indices, edit arguments, atoms, or a supplied decomposition are invalid or incompatible.
RuntimeError – If a fresh default NNLS decomposition fails its KKT certification, or an edit postcondition is violated.
- Warns:
UserWarning – If the source/target pair is near-parallel, the normalized edit basis is rank deficient or poorly conditioned, or
alphaextrapolatescoordinates_afteroutside the nonnegative pursuit frame. All three are non-fatal.
- transformer_lens.tools.analysis.sweep_sparse_probe(features: Float[Tensor, 'example feature'], labels: Bool[Tensor, 'example'] | Integer[Tensor, 'example'], *, ks: Sequence[int], test_fraction: int | float = 0.3, positive_label: int | bool = 1, groups: Integer[Tensor, 'example'] | None = None, preprocess: str = 'none', std_floor: int | float = 0.001, class_weight: str | None = 'balanced', l2_strength: int | float = 0.01, n_random_subsets: int = 0, n_label_shuffles: int = 0, seed: int = 0, max_iter: int = 200, max_refinement_steps: int = 25, decrement_tolerance: int | float = 1e-12) SparseProbeSweep¶
Fit sparse probes and optional controls over one fixed train/test split.
ksmust contain strictly increasing positive integers. Random-coordinate controls sample supports without replacement. Label-shuffle controls permute training labels, repeat selection and fitting, then evaluate against the untouched held-out labels. Control arrays contain raw metrics and do not represent automatic significance tests.- Parameters:
features – Finite float16/bfloat16/float32/float64 tensor shaped
[example, feature].labels – Boolean or integer binary labels shaped
[example].ks – Strictly increasing unique sparsity levels.
test_fraction – Requested held-out fraction within each class. With
groupsit targets held-out rows per class, which whole groups only approximate.positive_label – Label defining the positive class and score sign.
groups – Optional integer group IDs; each group is held out whole, with both classes on both sides. Groups may mix classes, but each class must appear in two or more.
preprocess –
"none"or train-only"standardize".std_floor – Lower bound on a non-constant column’s
"standardize"scale, shared by every fit;0disables it.class_weight –
"balanced"orNone, shared by every fit.l2_strength – Positive coefficient penalty shared by every fit.
n_random_subsets – Random-coordinate control fits per sparsity level.
n_label_shuffles – Shuffled-training-label control fits per sparsity level.
seed – Local CPU-generator seed for splitting and controls.
max_iter – Maximum LBFGS iterations per fit before Newton refinement. LBFGS also stops once its function evaluations reach
max_iter * 5 // 4(stop_reason="max_eval"; the line search can finish one past it), a budget equal tomax_iterwhenmax_iter <= 3.max_refinement_steps – Maximum damped Newton steps per fit; zero only checks.
decrement_tolerance – Largest accepted Newton decrement
g^T H^-1 g / 2per fit, an estimate of the objective gap to the optimum in nats; a larger gap raises.
- Returns:
Main probe results plus aligned raw control distributions. A control fit that fails to converge is excluded and recorded in
rejectionsrather than aborting the sweep, so completed fits survive; each control’s rows cover only its converged repeats.- Raises:
ValueError – If the grid, controls, inputs, groups, or options are invalid.
SparseProbeConvergenceError – If a main-probe fit fails to converge. Control-fit convergence failures do not raise here — they are collected in
SparseProbeSweep.rejections; any other error still propagates.