Views
No views yet
jimage_final_lens.pt) plus a short usage script.
tower · tall · towering. It also correctly names the building
(Meenakshi Amman Temple, Madurai), and nearby patches read temple · Hindu · religious,
pyramid (its stepped shape) and even scaffolding / unfinished.city · urban · distant. From an almost featureless hazy patch, the
model infers a distant city.smaller · taller · shorter. Not a label —
the model is comparing sizes between buildings.
cross · crucifix. From a small shape it infers the
Christian symbol (and, in the readout for the tower below it, church · bell · Christianity).purple — the model reads the colour of the person's
jacket, and the patch below reads walking. A fine-grained inference about someone
barely a few pixels tall.
football · football-field · stadium. From grass and painted
lines it infers the sport — and other patches read touchdown · NCAA · seating.J_l (one per layer). Applying J_l to a patch's internal
vector and decoding with the model's own output layer gives the readout:readout_l(h) = softmax( W_U · norm( J_l · h ) ), whereJ_l = E[ ∂h_final,t' / ∂h_l,t ]
J_l is the average effect a patch's activation has on what the model eventually says. We
fit it with image tokens as the source and the text that follows the image as the
target — so it captures how each patch shapes the model's answer. (Plain "logit-lens" fails
on image tokens; the Jacobian's future-averaging is what makes this work.)Qwen/Qwen3.5-27B (bf16, 64 layers, d_model 5120; unified vision-language,
early fusion; image placeholder token id 248056).‖J̄_l‖ sits on a broad plateau
from L16 through L54 before collapsing (L62 ≈ 0 — it's the target layer), but readout
quality peaks at L40–50 (held-out retrieval maximum at L46 — a good default;
L50 is equivalent). L62 is a degenerate/empty layer.1pip install "transformers==5.8.1" accelerate flash-linear-attention pillow \
2 git+https://github.com/anthropics/jacobian-lens.git
3python apply_example.py your_image.jpg1from jlens.lens import JacobianLens
2lens = JacobianLens.load("jimage_final_lens.pt") # source layers 16..62; use 46
3# h = a patch's residual [d] from Qwen3.5's language_model at layer 46
4logits = model.lm_head(model.norm(lens.transport(h, 46))) # top-k words = the readoutapply_example.py (with the bundled mm.py adapter) shows the full path, including mapping
an image-token index to its (row, col) patch via the processor's image_grid_thw
(patch 16 · spatial-merge 2 → each token ≈ a 32×32-px region).jimage_final_lens.pt — the fitted lens (layers 16–62, n=30; ~1.2 GB)jimage_L48-62_n120_lens.pt — the original release (layers 48–62, n=120; ~400 MB), kept for reproducibility — per-layer Jacobians are independent, so its layers agree with the full-depth fitapply_example.py, mm.py — minimal usage + the multimodal jlens adapterexamples/ — the highlighted example images abovecity / 城市).cc-by-nc-4.0, inherited from the MMDU data used to fit the lens (non-commercial). The
base model is Apache-2.0; the Jacobian-lens method and jlens library are Apache-2.0
(anthropics/jacobian-lens). Example images
are Wikipedia-sourced via MMDU, shown for illustration.