The model we interpret should be the same computational artifact that exhibits the behavior of interest.
Part 0: Getting attention weights can make a model behave differently
A while ago, I was analyzing the attention patterns of a vision-language model when I noticed something strange: its accuracy on my benchmark dropped from about 70% to 20% after I enabled output_attentions=True. I hadn't changed anything else other than that one argument for output_attentions. How could observing the model change its behavior so much?
One warning message caught my eye:
`torch.nn.functional.scaled_dot_product_attention` does not support `output_attentions=True`. Falling back to eager attention. This warning can be removed using the argument `attn_implementation="eager"` when loading the model.
So, requesting attention weights changed the attention implementation. The model I was trying to inspect was no longer being executed in the same way as the model whose behavior interested me.
Motivated by the huge performance drop, I wanted to understand whether switching attention implementations really could change model outputs, how much floating-point precision mattered, and whether there was a way to recover attention weights without switching away from the original computation.
That also leads to a broader question for interpretability: how do we make sure that we are studying the computational artifact that actually exhibited the behavior of interest?
Part I: Same weights can produce different behavioral outputs under different attention implementations
Attention implementations are supposed to compute the same underlying operation. But mathematically equivalent doesn't always mean numerically identical: fused kernels may group and round floating-point operations differently. The practical question is whether these numerical differences can lead to different observed model behavior (i.e. generated text). In the meantime, small rounding errors that do not lead to a difference in behavior would be fine and should not be a big problem.
I compared three attention backends while holding everything else fixed:
- Eager: Hugging Face
attn_implementation="eager", which explicitly materializes attention weights. - SDPA:
attn_implementation="sdpa", using PyTorch's regular scaled-dot-product-attention dispatch. - FA2:
attn_implementation="flash_attention_2", using the external FlashAttention 2 package.
All continuations below use greedy decoding to make sure the process is deterministic. If two runs generate different token sequences, the difference cannot be attributed to random token sampling, and must be from the attention implementation.
The same input results in different continuations
We begin with Qwen3-VL-4B-Instruct in BF16, using the prompt "Describe the image." and a COCO image of a bakery counter.
The identical input image for all three BF16 generations: COCO val2017 image 226903. Prompt: “Describe the image.”
The full greedy generations are shown below. Yellow highlights mark spans differing from both other backends under pairwise word/punctuation alignment.
| Implementation | Greedy description (128-token cap) |
|---|---|
| Eager | This is a photograph of a bakery or café’s display counter, likely set up for a special event or a busy morning. The counter is made of a light-colored, possibly stainless steel or white laminate, and is filled with an assortment of freshly prepared pastries and desserts. Key elements in the image: - **Desserts**: The counter is laden with various sweet treats. In the center, there’s a large, layered cake with white frosting and a decorative top. Around it are smaller square cakes, some with chocolate or fruit toppings. There are also rectangular slices of what appears to be a fruit tart or cake with a dark topping |
| SDPA | This is a photograph of a bakery or café display counter, likely in a shop with a large window. The counter is made of a light-colored, possibly stainless steel or white laminate surface, and is filled with an assortment of baked goods and pastries. Key elements in the image: - **Pastries and Cakes**: The display features several types of desserts. In the center, there is a large, square cake with a light-colored frosting, possibly vanilla or cream cheese. Around it are smaller, rectangular slices of cake, some with dark chocolate or berry toppings. There are also several small, square pastries with a golden-brown |
| FA2 | This is a photograph of a bakery or café display counter, likely in a shop with a large window. The counter is made of a light-colored, possibly stainless steel or white laminate surface, and is filled with an assortment of baked goods and pastries. Key elements in the image: - **Pastries and Cakes**: The display features several types of desserts. In the center, there is a prominent square cake with a white frosting and a dark topping, possibly chocolate or fruit. Around it are other cakes and pastries, some with chocolate or berry toppings, and others that appear to be layered or filled. There are also small, |
All three executions describe roughly the same scene, but the details and wording diverge.
To see whether this was an isolated example, I ran the same prompt on 20 randomly sampled COCO images. The counts below shows whether the there exists any generated different token among the output sequences between each pair of backends:
| Backend comparison | Images with different continuations |
|---|---|
| Eager vs. SDPA | 17/20 |
| Eager vs. FA2 | 17/20 |
| SDPA vs. FA2 | 15/20 |
15-17 out of 20 generations result in different output sequences across the three attention backends. While this does not necessarily mean they convey very different semantic information, it is already quite bothersome if we want to study some low-level/token-level mechanisms or predictions -- just by using another attention backend, the mechanism of interest may no longer be used.
Code: compare greedy text and next-token logits
from urllib.request import urlopen
import torch
from PIL import Image
from transformers import AutoModelForImageTextToText, AutoProcessor
model_id = "Qwen/Qwen3-VL-4B-Instruct"
processor = AutoProcessor.from_pretrained(model_id)
vlm = AutoModelForImageTextToText.from_pretrained(
model_id, dtype=torch.bfloat16, attn_implementation="eager",
).to("cuda").eval()
image = Image.open(urlopen(
"https://s3.amazonaws.com/images.cocodataset.org/val2017/000000226903.jpg"
)).convert("RGB")
messages = [{"role": "user", "content": [
{"type": "image", "image": image},
{"type": "text", "text": "Describe the image."},
]}]
inputs = processor.apply_chat_template(messages, tokenize=True,
add_generation_prompt=True, return_dict=True, return_tensors="pt").to("cuda")
def compare_backends(model, inputs, decoder, backends):
logits, texts = {}, {}
for backend in backends:
model.set_attn_implementation(backend)
with torch.inference_mode():
logits[backend] = model(**inputs, use_cache=False).logits[0, -1].cpu()
tokens = model.generate(**inputs, do_sample=False, num_beams=1,
max_new_tokens=128)
generated = tokens[0, inputs["input_ids"].shape[1]:]
texts[backend] = decoder.decode(generated, skip_special_tokens=True)
return logits, texts
backends = ["eager", "sdpa", "flash_attention_2"]
logits, texts = compare_backends(vlm, inputs, processor, backends)
for backend, text in texts.items():
print(backend, text)
The differences are visible in next-token logits
Different continuations can amplify small numerical changes over many generation steps. To take a closer look at the upstream cause, here I compare next-token logits on the identical image-and-prompt prefix.
For every input, I calculate the root-mean-squared difference between each pair of backends' logits, then average this value over the 20 inputs:
| Backend comparison (BF16) | Mean next-token logit RMSE |
|---|---|
| Eager vs. SDPA | 0.11302 |
| Eager vs. FA2 | 0.11435 |
| SDPA vs. FA2 | 0.087053 |
So the runs already have measurably different next-token scores on the same prefix, even before we compare their later continuations.
Another view: maximum absolute logit differences
For each input, I also compute the largest absolute difference over vocabulary entries, then average those per-input maximum values, to get a better sense of the magnitude of maximal differences.
| Backend comparison (BF16) | Mean per-image maximum absolute difference |
|---|---|
| Eager vs. SDPA | 0.51472 |
| Eager vs. FA2 | 0.54028 |
| SDPA vs. FA2 | 0.42119 |
Code: compute the averaged pairwise logit matrix
import torch
def pairwise_logit_differences(logits_by_input):
# One [backend, vocabulary] tensor per identical input prefix.
z = torch.stack(logits_by_input).double() # [input, backend, vocabulary]
difference = z[:, :, None, :] - z[:, None, :, :]
rmse = difference.square().mean(-1).sqrt().mean(0)
max_abs = difference.abs().amax(-1).mean(0)
return rmse, max_abs
# Opening example only. For the 20-input average, pass 20 such tensors.
logits_by_input = [torch.stack([logits[b] for b in backends])]
rmse, max_abs = pairwise_logit_differences(logits_by_input)
print(rmse)
print(max_abs)
Precision makes a substantial difference
If the choice of attention backend matters because of numerical computation, what happens when we change the floating-point precision?
I repeat the Qwen3-VL comparison on the same 20 inputs, holding precision fixed within each backend comparison:
| Precision | Different sequences: eager vs. SDPA | Mean next-token logit RMSE |
|---|---|---|
| BF16 | 17/20 | 0.11302 |
| FP16 | 6/20 | 0.016291 |
| FP32 | 0/20 | 0.000012276 |
The implementations agree much more closely at higher precision on these inputs. In FP32 especially, eager and SDPA generated identical token sequences across all 20 inputs, with a near zero logit RMSE difference. This pattern suggests that float number precision also plays an important role in determining model's behavior, as suggested in prior work (e.g. Qi et al., 2025).
However, since many models (such as the Qwen models) are trained in BF16 with flash attention and suggests inference to use the same setup, even if there is a better consistency across attention backends at FP32, switching to FP32 would cause a difference in behavior that is undesirable for carrying out interpretability analysis (see appendix for related comparisons).
Full FP16/FP32 comparisons, including FA2
| Precision | Backend comparison | Different sequences | Mean logit RMSE |
|---|---|---|---|
| FP16 | Eager vs. SDPA | 6/20 | 0.016291 |
| FP16 | Eager vs. FA2 | 4/20 | 0.018746 |
| FP16 | SDPA vs. FA2 | 6/20 | 0.014249 |
| FP32 | Eager vs. SDPA | 0/20 | 0.000012276 |
FA2 was unavailable in FP32 in this setup since it does not support this precision.
Code: repeat the VLM comparison at FP16 and FP32
import torch
from transformers import AutoModelForImageTextToText
# Reuse inputs, processor and compare_backends from the first example.
for dtype in (torch.float16, torch.float32):
methods = ["eager", "sdpa"]
if dtype == torch.float16:
methods.append("flash_attention_2") # FA2 does not support FP32.
precision_model = AutoModelForImageTextToText.from_pretrained(
model_id, dtype=dtype, attn_implementation="eager",
).to("cuda").eval()
z, text = compare_backends(precision_model, inputs, processor, methods)
print(dtype, text)
print(pairwise_logit_differences([torch.stack([z[b] for b in methods])])[0])
del precision_model
This isn't limited to vision-language models
Could this be a quirk of image inputs or Qwen3-VL? To check, I repeat the BF16 comparison on Qwen3-4B (a separately trained text-only model) and GPT-2 (the OG decoder-only transformer). Both models received the same 20 unfinished prose prefixes as literal text, with no chat template or special tokens added.
The following example shows the complete generations for both models, with differences highlighted.
Example: greedy continuations
Prefix: Fifty years later, the small coastal town had become
Both models use BF16 and greedy decoding. Yellow highlights mark spans that disagree with both other backends within that model.
Qwen3-4B
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | a major tourist destination, and the local government was trying to decide whether to build a new resort hotel. The town council was divided. Some council members thought that the hotel would bring in more tax revenue and create jobs. Others argued that the hotel would bring in too many tourists, which would strain the local infrastructure and environment. The council was also concerned about the impact of the hotel on local businesses, especially the local bed and breakfasts. The council wanted to know what the best course of action was. The council decided to consult an economic consultant. The consultant conducted a cost-benefit analysis of the hotel. The consultant found that the hotel |
| SDPA | a major tourist destination. The town's population had grown from 1,200 to 25,000. The town's economy had shifted from fishing and farming to tourism and retail. The town's infrastructure had also changed. The old stone bridge, which had once been the only bridge over the river, had been replaced by a modern, steel bridge. The town's old school, which had once been the only school in the town, had been replaced by a new, modern school. The town's old library, which had once been the only library in the town, had been replaced by a new, modern |
| FA2 | a major tourist destination. The town's population had grown from 1,200 to 25,000, with many more people visiting each year. The local government had built a new hotel, a few apartment buildings, and a number of restaurants. The town had a new name, "Seaside City." The town's new mayor, a young woman named Lillian, was determined to make sure that the town would continue to grow in a way that would be good for everyone. She wanted to make sure that the town would not become too crowded, that the environment would not be harmed, and that the town |
GPT-2
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | a tourist destination. "I was a little bit surprised to see the people there," said the man, who asked not to be named. "I was a little bit surprised to see the people there." The man said he was a member of the local council and was a member of the local council's board of directors. "I was a member of the local council and was a member of the local council's board of directors," he said. "I was a member of the local council's board of directors." The man said he was a member of the local council's board of directors and |
| SDPA | a tourist destination. "I was a little bit surprised to see the town, but I was surprised to see the people," said the man, who asked not to be named. "I was a little bit surprised to see the town, but I was surprised to see the people," said the man, who asked not to be named. "I was a little bit surprised to see the town, but I was surprised to see the people," said the man, who asked not to be named. "I was a little bit surprised to see the town, but I was surprised to see the people |
| FA2 | a tourist destination. "I was a little bit surprised to see the people there," said the man, who asked not to be named. "I was a little bit surprised to see the people there." The man said he was a member of the local council and was a member of the local council's board of directors. "I was a member of the local council and was a member of the local council's board of directors," he said. "I was a member of the local council and was a member of the local council's board of directors." The man said he was a |
Across the full 20-prefix sample:
| Model and input | SDPA vs. eager: different continuations | FA2 vs. eager: different continuations |
|---|---|---|
| Qwen3-VL, image descriptions | 17/20 | 17/20 |
| Qwen3-4B, prose prefixes | 18/20 | 15/20 |
| GPT-2, prose prefixes | 19/20 | 19/20 |
Differences across generated outputs are found in the tested text-only models too and it is not exclusive to VLMs.
The 20 continuation prefixes
- Just before dawn, a stranger arrived at the village carrying
- In a city without clocks, the morning began when
- Fifty years later, the small coastal town had become
- At the empty railway station, Mira turned to her friend and said,
- Behind the locked door, the forgotten room contained
- The letter arrived without a return address, and its first line read
- The invention looked ordinary until someone pressed
- After the storm, the forest path was covered with
- On the last evening before leaving home, Daniel found
- The festival began with a parade of
- For ten years the neighbors had never spoken, until one morning
- When people first learned to hear plants growing, they discovered
- "I think a place becomes home when," she said,
- On their first evening on the distant planet, the settlers noticed
- The market smelled of fresh bread and rain, and at the first stall
- Keeping the promise had seemed easy until
- The museum's most unusual exhibit was a glass case holding
- The small act of kindness seemed unimportant, but the next day
- Every time the traveler checked the map, the destination
- The unfamiliar key was warm in her hand, and beside it lay
Mean pairwise next-token logit RMSE, averaged over 20 inputs per checkpoint. These are within-model backend comparisons, not comparisons between different checkpoints.
Code: reproduce the two BF16 text-model controls
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
# One prefix is shown; use continuation20.json for the 20-prefix average.
prefix = "Fifty years later, the small coastal town had become"
for checkpoint in ("Qwen/Qwen3-4B", "openai-community/gpt2"):
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
lm = AutoModelForCausalLM.from_pretrained(
checkpoint, dtype=torch.bfloat16, attn_implementation="eager",
).to("cuda").eval()
text_inputs = tokenizer(prefix, add_special_tokens=False,
return_tensors="pt").to("cuda")
z, text = compare_backends(lm, text_inputs, tokenizer, backends)
print(checkpoint, text)
print(pairwise_logit_differences([torch.stack([z[b] for b in backends])])[0])
del lm
The interpretability problem remains: if requesting attention weights causes a switch from SDPA or FA2 to eager, we may end up measuring internal patterns from a run that doesn't even generate the same sequence as the original. What then should we do to (1) access faithful intermediate computational variables and (2) not change the model's native computation graph?
Part II: Recovering attention from fused kernels
Part I exposed a practical problem: the attention implementation that produces the behavior we want to understand may not expose its attention weights. With optimized backends such as SDPA and FlashAttention, the full attention matrix is often never materialized as an accessible tensor. Asking for it through output_attentions=True can instead switch the model to eager attention—and, as we've seen, switching implementations can change the generated continuation.
Can we recover the attention weights of the original backend without switching to a different implementation?
This is in principle doable. We don't need the kernel to return its attention matrix. We can patch the values supplied to it and observe its output. By choosing the values carefully, we can leverage the existing blackbox attention kernel to reconstruct the attention weights. This idea was suggested in this PyTorch discussion. I'll walk through the intuition, explain how to use it for long sequences, and then test how accurately it recovers attention from real backends.
1. The trick: reconstructing attention weights with identity value matrices
The final step of a single attention head is:
Here, \(A\) is the attention matrix we want, \(V\) contains the value vectors, and \(Z\) is the attention output. An optimized kernel may give us \(Z\) without ever exposing \(A\).
Consider the following observation: if we set \(V\) to an identity matrix, the output becomes \(A\) itself, via \(AI=A\).
That gives us a way to reconstruct attention weights using the original kernel. We leave all other variables unchanged, and replace only the value vectors.
In practice, the value dimension is usually much smaller than the sequence length, so we can't fit the entire identity matrix into a single attention call. We can use partial identities: each call reveals a block of columns, and several calls recover the complete matrix.
Reading attention from its output. (A) Replacing the value vectors with a partial identity reveals the corresponding columns of the attention matrix. (B) Shifting the identity entries across successive passes recovers the remaining columns, which are concatenated.
For example, if a sequence has six key positions but each value vector has only two dimensions, each identity-value pass reveals two columns of attention. Three passes recover all six columns. More generally, a sequence with \(T_k\) key positions and value dimension \(d_v\) takes \(\lceil T_k/d_v\rceil\) passes.
The key part is that this doesn't require the fused kernel to produce a full attention matrix internally. We reconstruct it from the kernel's responses to carefully chosen values.
Code: a minimal example of identity-value recovery
import torch
for length, head_dim in [(2, 4), (6, 2)]:
# Toy attention weights: the fused kernel is represented here by A @ V.
A = torch.softmax(
torch.randn(length, length, dtype=torch.float64), dim=-1
)
blocks = []
for offset in range(0, length, head_dim):
width = min(head_dim, length - offset)
V = torch.zeros(length, head_dim, dtype=A.dtype)
V[offset:offset + width, :width] = torch.eye(
width, dtype=A.dtype
)
Z = A @ V
blocks.append(Z[:, :width])
recovered = torch.cat(blocks, dim=-1)
torch.testing.assert_close(recovered, A, atol=0, rtol=0)
print((length, head_dim), recovered.shape)
2. Applying the trick to a real attention implementation
The mathematical idea is simple. To use it with a real transformer, we need access to the attention operation at the point where its values enter and its output leaves. We need to be able to replace intermediate value tensors and read intermediate outputs.
Using NNsight, we can do the following for a selected attention head on HF open-sourced models:
- Run the model with the desired setup, so that the queries and keys correspond to the computation we're studying.
- Repeat the attention computation with successive partial-identity value tensors, keeping the queries, keys, mask, and other attention settings fixed.
- Read each resulting attention output at the boundary before the output projection (
o_proj), and concatenate the recovered blocks to construct the full attention matrix.
Through these steps, we get both the behavior of interest, and the attention weights reconstructed from the corresponding runs.
There is one practical detail when extracting many layers or heads: replacing values at an early layer can change the inputs to later layers. If we want attention weights from the original later-layer computation, we must keep its inputs fixed. We use a clean cache built from an unmodified execution and restore the original activation before continuing to collect later layer attention weights: this reduces the number of runs we needed to reconstruct attention weights across all layers.
Implementation detail: recovering many heads without contaminating later layers
Attention head output activation restoration. When multiple layers are inspected in a shared computation, the original attention output can be restored after each identity-value pass so that subsequent layers receive their original inputs.
In our implementation, we record the clean attention output, perform each identity-value pass, save its output for reconstruction, and restore the clean output at the input to o_proj.
3. How good is the recovery?
There is another caveat. The equation \(Z=AV\) holds exactly in principle, but an optimized GPU kernel computes in finite precision and can fuse or reorder operations. The recovered matrix is therefore best viewed as a numerical approximation to the attention weights relevant to that backend.
To evaluate that approximation, we ask the following question: can the recovered attention matrix reconstruct the attention output observed during the original forward pass?
We first recover a matrix \(A_{\mathrm{pred}}\) using partial identities. Then we multiply it by the original value vectors \(V_{\mathrm{real}}\), and compare the prediction with the clean attention output \(Z(V_{\mathrm{real}})\) from the original forward pass.
We measure their difference as relative reconstruction error: a smaller percentage means the recovered matrix more closely reproduces the native kernel's output.
Evaluation details: reconstruction error and controls
Here, \(\|\cdot\|_F\) is the Frobenius norm. We compare against the output visible immediately before the attention output projection, using the native backend's own computation.
Inputs and head selection. Qwen3-VL-4B-Instruct uses the same 20 COCO images with “Describe the image” as the previous experiments. Qwen3-4B and GPT-2 use the same 20 unfinished prose prefixes.
We select three decoder layers and three heads per layer. Both Qwen models use layers 0, 17, 35 and heads 0, 16, 31; GPT-2 uses layers 0, 5, 11 and heads 0, 6, 11. In total, we have 3 models x 3 layers x 3 heads x 3 backends x 20 inputs = 1,620 comparisons.
Measurement and precision. Using NNsight, we record the original values and the clean activation immediately before the attention output projection. Native attention and identity-value patching run in BF16. The evaluation product \(A_{\mathrm{pred}}V_{\mathrm{real}}\) is computed in float64 to limit additional evaluation error.
Across all 1,620 comparisons, reconstruction errors range from 0.086% to 0.297%, with a mean of 0.182%. These results show that the recovered matrices thus closely reproduce the attention outputs observed during the original forward pass.
4. How does backend-recovered attention compare with the eager-returned attention weights?
We could also obtain attention weights from eager and use them to analyze a model run under SDPA or FA2. Part I gives us a reason to be cautious: separate backend executions can differ even when the inputs are identical. In this section, we compare the error from using the extracted attention weights from a run's own backend to the error from using the eager-returned attention weights. For Qwen3-VL decoder attention under FA2, for example, the mean errors are 0.192% with FA2-recovered weights and 10.593% with eager-returned weights.
Attention-output reconstruction error (%) — lower is better
| Model | Target backend | Recovered from target | Eager returned |
|---|---|---|---|
| Qwen3-VL-4B | Eager | 0.160% | 0.160% |
| Qwen3-VL-4B | SDPA | 0.192% | 8.135% |
| Qwen3-VL-4B | FA2 | 0.192% | 10.593% |
| Qwen3-4B | Eager | 0.152% | 0.152% |
| Qwen3-4B | SDPA | 0.196% | 1.361% |
| Qwen3-4B | FA2 | 0.197% | 1.361% |
| GPT-2 | Eager | 0.155% | 0.155% |
| GPT-2 | SDPA | 0.196% | 0.825% |
| GPT-2 | FA2 | 0.196% | 0.816% |
For both SDPA and FA2, using weights recovered from the target backend gives lower mean reconstruction error than using the eager-returned attention weights. This supports the use of backend-specific extraction when the goal is to explain the attention computation that actually ran.
5. Recovering attention in practice
I've packaged this approach as AttnRead so others can use it in their own research:
pip install attnread
Related issues reported online
Other users have encountered related problems when comparing or inspecting attention implementations:
- Different logits on image inputs. A Qwen2.5-VL discussion, also reported in Transformers issue #39067, describes larger backend logit differences for image inputs than for text inputs.
- Changed behavior while requesting attention weights. Transformers issue #35270 reports unexpected outputs when using eager attention to inspect a LLaVA model. It illustrates the practical concern that the attention-inspection configuration can affect the behavior being studied.
- Fused attention does not normally expose the full pattern. PyTorch issue #119811 discusses this interpretability need and suggests probing with identity values.
Discussion
When we say we are interpreting a model, what exactly identifies that model? A checkpoint specifies its parameters, but those parameters can be executed through different computational implementations. As we've seen, changing the attention backend or floating-point precision can produce different greedy continuations, even when the model weights, inputs, and decoding settings remain fixed. In practice, a checkpoint alone does not fully specify the computational artifact whose behavior we are trying to explain.
This matters when our interpretability methods require modifying how the model is executed. Suppose a model exhibits some behavior under a fused attention backend, but requesting its attention weights silently switches the implementation to eager. The resulting attention patterns may come from an execution that behaves differently on the very input we're interested in. Even if the two executions produce similar outputs, we cannot simply assume that their internal computations are interchangeable.
Our approach to attention recovery illustrates one way forward: rather than changing the computation to make it easier to inspect, we can design our measurements around the computation we actually want to understand. By recovering attention weights directly from the original backend, and validating them against its native outputs, we can establish a closer connection between the quantities we extract and the computation that produced them.
Of course, not every numerical difference between implementations will matter for every interpretability question. Different token sequences do not necessarily imply different semantic behavior, and small numerical discrepancies need not invalidate an analysis. What matters is whether the measurements we obtain faithfully characterize the computation relevant to the phenomenon we're studying.
The broader lesson extends beyond attention visualization. Whenever an interpretability method changes the execution environment, numerical precision, or computation being inspected, we should ask whether those changes affect what we're trying to explain. Before explaining a model's behavior, we need to establish that we're interpreting the computation that produced it.
Appendix: eager generation across precisions
Qwen-VL
The comparisons above change the attention implementation while holding precision fixed. We can also hold eager attention fixed and change precision. On the same 20 Qwen-VL images, pairwise counts of different greedy token sequences are:
| Eager precision | BF16 | FP16 | FP32 |
|---|---|---|---|
| BF16 | 0 | 18/20 | 18/20 |
| FP16 | 18/20 | 0 | 8/20 |
| FP32 | 18/20 | 8/20 | 0 |
We see that with the same attention backend, changing the float number precision significantly alters the model's token level behavior. FP16 and FP32 produce relatively closer outputs, and BF16 produces very different outputs from the other two precisions we tested.
Text models
The same 20 raw continuation prefixes are used in BF16, FP16, and FP32. Holding eager fixed gives these counts of different greedy continuations:
| Eager checkpoint | BF16 vs FP16 | BF16 vs FP32 | FP16 vs FP32 |
|---|---|---|---|
| Qwen3-4B | 15/20 | 14/20 | 7/20 |
| GPT-2 | 20/20 | 20/20 | 15/20 |
Text models also show similar patterns: with the eager backend fixed, changing float precisions significantly change their token-level behaviors and lead to divergent generated sequences.
The within-precision backend controls on those same prefixes are:
| Checkpoint | Precision | SDPA vs eager | FA2 vs eager | Mean SDPA logit RMSE |
|---|---|---|---|---|
| Qwen3-4B | FP16 | 6/20 | 7/20 | 0.013151 |
| Qwen3-4B | FP32 | 0/20 | Unavailable | 5.2948e-06 |
| GPT-2 | FP16 | 9/20 | 10/20 | 0.03886 |
| GPT-2 | FP32 | 0/20 | Unavailable | 1.0622e-05 |
FP16 reduces the divergent generated sequences by a lot, and under FP32 there is no divergent behavior between eager and SDPA backends, which is consistent with the patterns we see in the main post. FA2 is unavailable in FP32.
Appendix: five more images with different continuations
We show five more examples of the qualitatively different continuations from different attention backends from the qwen VL model.
COCO image 295809
COCO val2017 image 295809. BF16, fixed checkpoint, prompt: “Describe the image.”
| Implementation | Greedy description (128-token cap) |
|---|---|
| Eager | This is a low-angle, eye-level photograph taken from the perspective of a cyclist or pedestrian standing on a paved street, looking down the road. The most prominent feature is a large, white painted bicycle symbol (a stylized bike) on the asphalt, which indicates a designated bike lane or path. Above the bike symbol, two white arrows point straight ahead, reinforcing the direction of travel. The street is wide and appears to be in an urban or suburban setting, with multi-story brick and stone buildings lining both sides. The architecture suggests a historic or established neighborhood. Several traffic lights are visible, including one at the intersection in the foreground and |
| SDPA | This is a low-angle, eye-level photograph taken from the perspective of a cyclist or pedestrian standing on a paved street, looking down the road. The most prominent feature is a large, white painted bicycle symbol (a stylized bike) on the asphalt, which marks a designated bike lane. The symbol is centered in the foreground and is clearly visible against the dark pavement. The street itself is wide and appears to be in a city or urban area. Two solid yellow lines run down the center of the road, separating traffic moving in opposite directions. The road stretches into the distance, flanked by multi-story buildings on both sides. The architecture |
| FA2 | This is a low-angle, eye-level photograph taken from the perspective of a cyclist or pedestrian standing on a paved street, looking down the road. The most prominent feature is a large, white painted bicycle symbol (a stylized bike) on the asphalt, which is part of a designated bike lane. Above the bike symbol, there are two white, parallel, chevron-like arrows pointing straight ahead, indicating the direction of travel for cyclists. The street is wide and appears to be in an urban or suburban setting, with multi-story brick and stone buildings lining both sides. The architecture suggests a historic or older part of a city. On the |
COCO image 557884
COCO val2017 image 557884. BF16, fixed checkpoint, prompt: “Describe the image.”
| Implementation | Greedy description (128-token cap) |
|---|---|
| Eager | This is a photograph of a small, trailing green plant, likely a pothos (Epipremnum aureum), growing in a clear glass test tube or small vase. The plant is mounted on a light-colored, possibly white or pale green, wall, with its vines cascading downwards and outwards. Key details: - The plant has heart-shaped, glossy green leaves. - Some leaves are a lighter, more yellowish-green, possibly indicating new growth or natural variation. - The plant is contained in a clear glass vessel that is mounted to the wall, likely using a clip or adhesive, allowing the plant to grow vertically and |
| SDPA | This is a photograph of a small, trailing green plant, likely a pothos (Epipremnum aureum), growing in a clear glass test tube or small vase. The plant is mounted on a light-colored, possibly white or pale green, wall, with its vines cascading downwards and outwards. Key details: - The plant has heart-shaped, glossy green leaves, some of which are slightly yellowing or have brown edges, suggesting it may be a bit stressed or older. - The stems are thin and vine-like, with some leaves hanging down and others extending horizontally. - The plant is contained within a clear glass vessel |
| FA2 | This is a photograph of a small, trailing green plant, likely a pothos (Epipremnum aureum), growing in a clear glass test tube or small vase. The plant is mounted on a light-colored, possibly white or pale green, wall, with its stems and leaves cascading downwards. Key details: - The plant has heart-shaped, glossy green leaves and long, slender vines. - The glass container is positioned in the corner, holding water and possibly some roots, suggesting it's being grown hydroponically or in a water-based system. - The lighting is soft and diffused, creating a gentle, slightly h |
COCO image 173057
COCO val2017 image 173057. BF16, fixed checkpoint, prompt: “Describe the image.”
| Implementation | Greedy description (128-token cap) |
|---|---|
| Eager | This is a bright, sunny day in a public square, centered around a prominent, modern clock tower. The tower is constructed from dark, possibly black, metal and has a distinctive, multi-tiered design. It features four large, white-faced clocks with black Roman numerals and hands, visible on its four sides. The tower is mounted on a large, rectangular base that incorporates a shallow, rectangular fountain with turquoise-colored water. The fountain is surrounded by low, dark stone or concrete benches where several people are sitting and relaxing. In the background, there is a large, multi-story building with a modern facade of grey panels and numerous windows |
| SDPA | This is a bright, sunny day in a public square, centered around a tall, modern clock tower. The tower is constructed of dark metal and glass, with a distinctive design featuring a central vertical shaft and a square base. It has two visible clock faces, both showing Roman numerals, with the top clock face displaying approximately 10:10 and the bottom one showing approximately 10:15. The tower is surrounded by a shallow, rectangular water feature that reflects the sky and the building behind it. In the foreground, several people are relaxing on the edge of the water feature, sitting on low stone benches. Some |
| FA2 | This is a bright, sunny day in a public square, centered around a prominent, modern clock tower. The tower is constructed from dark metal and glass, with a distinctive design featuring a central vertical shaft and a square base. It has two visible clock faces, each with Roman numerals, set within a dark, maroon, and white panelled frame. The clock hands indicate a time of approximately 10:10. At the base of the tower is a large, shallow, rectangular fountain with a turquoise-colored water surface. The fountain is surrounded by a low, dark stone or concrete ledge, where several people are sitting and |
COCO image 102331
COCO val2017 image 102331. BF16, fixed checkpoint, prompt: “Describe the image.”
| Implementation | Greedy description (128-token cap) |
|---|---|
| Eager | This is a dynamic action photograph capturing a motocross rider mid-air during a race or practice session on a dirt track. **Main Subject:** - A rider wearing a bright green and black motocross suit and a matching green helmet with a visor is airborne on a green and white dirt bike. - The rider is leaning forward, gripping the handlebars, and appears focused on the landing. **The Motorcycle:** - The bike is a green Kawasaki, likely a 250 or 450 model, with a white front fender and a visible engine. - It is captured in mid-jump, with |
| SDPA | This is a dynamic action photograph capturing a motocross rider mid-air during a jump on a dirt track. **Main Subject:** - A rider wearing a bright green and black motocross suit and a matching green helmet with a visor is the focal point. - The rider is leaning forward, gripping the handlebars, and appears to be in control as they soar through the air. **The Motorcycle:** - The bike is a green and white dirt bike, likely a Kawasaki, with a visible engine and suspension. - It is airborne, with its front and rear wheels off the ground, indicating a jump. **Setting: |
| FA2 | This is a dynamic action photograph capturing a motocross rider mid-air during a jump on a dirt track. **Main Subject:** - A rider wearing a bright green and black motocross suit and a matching green helmet with a visor is the focal point. - The rider is leaning forward, gripping the handlebars, and appears to be in control as they soar through the air. **The Motorcycle:** - The motorcycle is a green and white dirt bike, likely a Kawasaki, given the green color scheme and the visible engine design. - It is airborne, with its front and rear wheels off the ground, showcasing the power |
COCO image 195165
COCO val2017 image 195165. BF16, fixed checkpoint, prompt: “Describe the image.”
| Implementation | Greedy description (128-token cap) |
|---|---|
| Eager | This image shows a bathroom stall, likely in a public or commercial setting such as a hotel, office, or school. The stall is separated by a beige, slightly textured partition wall with a small, square, metallic fixture (possibly a lock or handle) near the top. The stall has a dark, speckled countertop with a white oval sink. Above the sink, mounted on the wall, are two dark blue or black wall-mounted paper towel dispensers. To the right of the sink, there is a small shelf holding various toiletries, including bottles of soap, lotion, and other personal care items. A small stack of |
| SDPA | This image shows a bathroom stall, likely in a public or commercial setting such as a hotel, office, or school. The stall is separated by a beige, slightly worn partition wall with a small, square metal fixture near the top. The stall has a dark countertop with a white sink and a chrome faucet. Above the sink, there are two dark blue, wall-mounted paper towel dispensers. To the right of the sink, there is a small shelf holding various toiletries, including bottles, a bowl of colorful candies, and a stack of small white cups. A black trash can is visible in the foreground, and a blue plastic |
| FA2 | This image shows a public restroom, likely in a hotel, office, or similar establishment, with a focus on a single stall and its adjacent sink area. The space is compact and functional, with a warm, somewhat dim lighting that gives it a slightly dated or utilitarian feel. Key elements in the image: - **Stall Partition**: A beige or tan partition wall separates the stall from the sink area. A small, square, metallic fixture (possibly a lock or latch) is visible on the wall. - **Sink and Counter**: A dark, possibly granite or laminate countertop holds a white, oval-shaped sink. A white towel |
Appendix: five more prefixes with different continuations
We show five more examples of the qualitatively different continuations from different attention backends for the text models.
Prefix 7
Prefix: The invention looked ordinary until someone pressed
Qwen3-4B
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | the button and the door opened. The invention was a ______. (A). door (B). safe (C). vault (D). safe deposit box Answer: Answer: B. safe The invention looked ordinary until someone pressed the button and the door opened. The invention was a safe. A safe is a secure container for valuables, often with a lock and a key or a combination. It may have a button that, when pressed, allows the door to open. The other options, such as a door, vault, or safe deposit box, do not typically have a button that opens the door. A door |
| SDPA | the button and the door opened. The invention was a ______. (A). door (B). safe (C). vault (D). safe deposit box Okay, let's try to figure out this question. The sentence says, "The invention looked ordinary until someone pressed the button and the door opened. The invention was a ______." The options are door, safe, vault, or safe deposit box. First, I need to understand the context. The key part here is that the invention seemed ordinary at first, but when you press a button, the door opens. So, the thing in question is something that's not |
| FA2 | the button and the door opened. The invention was a ______. (A). door (B). safe (C). vault (D). safe deposit box Okay, let's try to figure out this question. The sentence says, "The invention looked ordinary until someone pressed the button and the door opened. The invention was a ______." The options are door, safe, vault, or safe deposit box. First, I need to understand the context. The key part here is that the invention looked ordinary but had a hidden mechanism that opened when a button was pressed. So, the thing in question is something that appears normal but |
GPT-2
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | the button. "I'm not sure if it's a coincidence or not," he said. "I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I think it's a coincidence. I |
| SDPA | the button. "I'm not sure if it's a coincidence or not," he said. "I don't know if it's a coincidence or not." The device is a small, light-emitting diode that can be used to detect the presence of a substance, such as a drug, in a person's body. The device is a small, light-emitting diode that can be used to detect the presence of a substance, such as a drug, in a person's body. The device is a small, light-emitting diode that can be used to detect |
| FA2 | the button. "I'm not sure if it's a coincidence or not," he said. "I don't know if it's a coincidence or not." The device is a small, light-emitting diode that can be used to detect the presence of a chemical or biological substance. The device is a small, light-emitting diode that can be used to detect the presence of a chemical or biological substance. The device is a small, light-emitting diode that can be used to detect the presence of a chemical or biological substance. The device is a small |
Prefix 8
Prefix: After the storm, the forest path was covered with
Qwen3-4B
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | a layer of leaves. The path was 0.5 miles long and 30 yards wide. How many square yards are in the path? To find the area of the path in square yards, we need to convert the length from miles to yards and then multiply by the width in yards. First, we know that 1 mile is equal to 1760 yards. So, 0.5 miles is equal to 0.5 * 1760 = 880 yards. The width of the path is already given in yards, which is 30 yards. Now, we can calculate |
| SDPA | a layer of leaves. The path was 0.5 miles long and 10 yards wide. How many square yards of leaves were on the path? To find the area of the path in square yards, we need to convert the length from miles to yards and then multiply by the width. First, we know that 1 mile is equal to 1760 yards. So, 0.5 miles is equal to 0.5 * 1760 = 880 yards. The width of the path is given as 10 yards. Therefore, the area of the path is 8 |
| FA2 | a layer of leaves. The path was 0.5 miles long. Each leaf is 0.001 inches thick. If there were 5000 leaves on the path, how many inches thick is the layer of leaves on the path? To solve this problem, we need to calculate the total thickness of the layer of leaves on the path. Here's how we can approach it: 1. **Understand the given information:** - The path is 0.5 miles long. - Each leaf is 0.001 inches thick. - There are 5000 leaves |
GPT-2
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | snow, and the wind was blowing in the direction of the city. "I'm sorry, but I can't do anything." "I'm sorry, but I can't do anything." "I'm sorry, but I can't do anything." "I'm sorry, but I can't do anything." "I'm sorry, but I can't do anything." "I'm sorry, but I can't do anything." "I'm sorry, but I can't do anything." "I'm sorry, but I can't do anything." |
| SDPA | snow and the wind was blowing. "I'm not going to be able to go back to the village, I'm going to be in the forest. I'm not going to be able to go back to the village, I'm going to be in the forest. I'm not going to be able to go back to the village, I'm going to be in the forest. I'm not going to be able to go back to the village, I'm going to be in the forest. I'm not going to be able to go back to the village, I'm going to be in the forest. I'm not |
| FA2 | snow, and the wind was blowing in the direction of the village. "I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry, I'm sorry |
Prefix 11
Prefix: For ten years the neighbors had never spoken, until one morning
Qwen3-4B
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | , the old man was in the garden, and the young man came to visit. The old man said, "I have been waiting for you for ten years." The young man said, "I have been waiting for you for ten years." They both said it. They both waited for each other. They both waited for the other to speak first. They both waited for the other to make the first move. They both waited for the other to break the silence. They both waited for the other to take the first step. They both waited for the other to take the first step. They both waited for the other to take the first |
| SDPA | , the old man was in the garden, and the young man was in the house, and the old woman was in the garden, and the young woman was in the house. What is the answer to this riddle? The answer is that they were all in the same place at the same time, but in different locations. The old man was in the garden, the young man in the house, the old woman in the garden, and the young woman in the house. So, they were all in the same place, but the old man and the old woman were in the garden, while the young man and the young woman were |
| FA2 | , the old man was in the garden, and the young man was in the house, and the old woman was in the garden, and the young woman was in the house. What is the answer to this riddle? The answer to this riddle is that the old man and the young man are the father and son, and the old woman and the young woman are the mother and daughter. The key is that the old man and the young woman are in the garden, and the young man and the old woman are in the house. This is a play on the ages of the people and their locations. The riddle is a |
GPT-2
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | , when a man came to the door of the house and said, "I have a question for you." "I have a question for you," said the man, "for what?" "I have a question for you," said the man, "for what?" "I have a question for you," said the man, "for what?" "I have a question for you," said the man, "for what?" "I have a question for you," said the man, "for what?" "I have a question for you," said the man, "for |
| SDPA | , when the man who had been the first to leave, a man named John, came to the house. He was a man of good character, and a man of good character, and a man of good character. He was a man of good character, and a man of good character. He was a man of good character, and a man of good character. He was a man of good character, and a man of good character. He was a man of good character, and a man of good character. He was a man of good character, and a man of good character. He was a man of good character, and |
| FA2 | , when a man came to the door and said, "I have a question for you." "I don't know," said the man. "I don't know what you're talking about." "I don't know," said the man. "I don't know what you're talking about." "I don't know," said the man. "I don't know what you're talking about." "I don't know," said the man. "I don't know what you're talking about." "I don't know," said the man. "I don't know |
Prefix 12
Prefix: When people first learned to hear plants growing, they discovered
Qwen3-4B
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | that plants could be used to produce sound. This is a very important discovery. What is the main idea of this paragraph? The main idea is that plants can produce sound, which is an important discovery. The paragraph is about the discovery that plants can produce sound, and the author emphasizes the importance of this discovery. The main idea is that plants can produce sound, which is an important discovery. The paragraph is about the discovery that plants can produce sound, and the author emphasizes the importance of this discovery. The main idea is that plants can produce sound, which is an important discovery. The paragraph is about the discovery that plants |
| SDPA | that plants could be used to produce sound. This is a very important discovery, and it is the beginning of a new era in science. Which of the following statements is correct? ( ) A. The statement that plants can produce sound is a scientific fact. B. The statement that plants can produce sound is a scientific hypothesis. C. The statement that plants can produce sound is a scientific theory. D. The statement that plants can produce sound is a scientific law. Answer: B The main reason for the formation of the 'Tian Shan' mountain range is ____ A. The collision between the Eurasian Plate and the Indian |
| FA2 | that plants could be used to produce sound. This is a metaphor, right? Because plants don't actually produce sound. But the idea that plants can be used to produce sound is a metaphor for something else. What is that something else? The statement you're referring to is a metaphor, and it's likely drawing a parallel between the natural processes of plants and human-made systems that generate sound. The metaphor suggests that just as plants can be used to produce sound (in a metaphorical or symbolic sense), there might be a way to harness natural processes or elements to create or influence sound in a more profound or meaningful way. In a more |
GPT-2
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | that they were actually growing plants. "I think that's the first time that we've really had a real understanding of the plant's biology," said Dr. David S. Siegel, a plant biologist at the University of California, San Diego. The study, published in the journal Plant Ecology and Evolution, is the first to show that plants are able to grow in a way that is similar to the way they do in the wild. "The plants that we've grown in the wild are very different from the ones that we've grown in the laboratory," said Dr. Siegel, who is also a |
| SDPA | that they were actually growing plants. "The plants were growing in a very different way," said Dr. David S. Siegel, a plant biologist at the University of California, San Diego. "They were growing in a very different way." The plants were growing in a very different way The plants were growing in a very different way. "The plants were growing in a very different way," Siegel said. "They were growing in a very different way." The plants were growing in a very different way The plants were growing in a very different way. "The |
| FA2 | that they were actually growing plants. "The plants were growing in a way that was very different from what we were used to," said Dr. David S. Siegel, a plant biologist at the University of California, San Diego. "The plants were growing in a way that was very different from what we were used to," said Dr. Siegel, who is also a plant biologist at the University of California, San Diego. The plants were growing in a way that was very different from what we were used to. "The plants were growing in a way that was very different from what we |
Prefix 13
Prefix: "I think a place becomes home when," she said,
Qwen3-4B
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | "you can't imagine life without it." That's from a 2013 article in the New York Times about a woman who had lived in New York for 50 years and was about to move to a small town in Vermont. The article was about how people often think of home as a place of comfort and familiarity, but the woman said that home is more than that. It's a place that you can't imagine life without. So, the question is, what is home to you? What is it to me? What is it to you? What is it to the person you love? What is it to |
| SDPA | "you can't imagine life without it." 1. What is the main idea of the sentence? 2. What is the main idea of the paragraph? 3. What is the main idea of the passage? 4. What is the main idea of the whole text? Okay, let's tackle these questions. The user provided a single sentence and is asking about the main ideas at different levels: the sentence, the paragraph, the passage, and the whole text. But wait, the user only gave one sentence. So maybe they're assuming that the paragraph and passage are the same as the sentence? Or perhaps there |
| FA2 | "you can't imagine life without it." That's from a 2013 article in the New York Times about a woman who had lived in New York for 50 years and was about to move to a small town in Vermont. The article was about how people often think of home as a place of comfort and familiarity, but the woman said that home is more than that. It's a place where you can't imagine life without it. So, the question is, what is home to you? What is it to me? What is it to you? What is it to me? What is it to you? |
GPT-2
| Implementation | Greedy continuation (128-token cap) |
|---|---|
| Eager | "and I think that's what we're going to do." The new home will be a "home for the kids," she said. "I think that's what we're going to do," she said. The new home will be a "home for the kids," she said. "I think that's what we're going to do," she said. The new home will be a "home for the kids," she said. "I think that's what we're going to do," she said. The new home will be a "home for the kids |
| SDPA | "and I think that's what we're going to do." The first time she was in the hospital, she was diagnosed with a rare form of cancer. "I was in the hospital for a month and a half, and I was in the hospital for a month and a half," she said. "I was in the hospital for a month and a half, and I was in the hospital for a month and a half, and I was in the hospital for a month and a half, and I was in the hospital for a month and a half, and I was in the hospital for a month and a |
| FA2 | "and I think that's what we're going to do." The first time she was in the hospital, she was diagnosed with a rare form of cancer. "I was in a coma for a week and a half," she said. "I was in a coma for a week and a half, and I was in a coma for a week and a half. I was in a coma for a week and a half, and I was in a coma for a week and a half. I was in a coma for a week and a half, and I was in a coma for a week and a half. |
Citation
If you want to cite this post, please use the following citation.
@misc{hua2026interpreting,
author = {Hua, Etha Tianze},
title = {Are we interpreting the model of interest?},
year = {2026},
month = Nov,
howpublished = {Blog post},
url = {https://ethahtz.github.io/blogs/model_of_interest.html}
}