Join the conversation

Join the community of Machine Learners and AI enthusiasts.

Sign Up
tetracta 
posted an update 17 days ago
Post
106
We put Qwen2.5-3B and its Instruct fine-tune under an X-ray — layer by layer, two scans running side by side on our GPU fleet.

🩺 Structural comparison (base → instruct): the change starts at layer 4 and spreads across 33 of 37 measurement points (~89% of the scanned depth) — in this pair, instruction tuning is not a "last few layers" story.

🧠 Knowledge delta, on a 20-item probe set: every fact the base model knew survived (18/20 → 18/20, zero broken), and fabrication-avoidance improved from 13/20 to 18/20. The internal true/false separation signal got slightly weaker (AUROC 0.915 → 0.878) — an honest trade-off worth knowing about.

Full interactive reports (no login needed):
🔗 structure: https://www.tetracta.ai/llm_tomografi/r/a048cc12934d488aa415d0ee0c1abeca/eGWvi64CrsRQAwFirfqmVg
🔗 knowledge: https://www.tetracta.ai/llm_tomografi/r/d0a0a6ea76f04b59b35307313b7e1cf0/WHH9qVypf4j0Fd6XPjP7Yw

Model X-Ray is in free open beta — 20 scans per account, any public safetensors checkpoint up to 7B, running on our own small GPU fleet: https://www.tetracta.ai/xray.html

If you fine-tune or merge models: scan your checkpoint before and after, and tell us what you see — we answer every message.

سلام خوبی

·

سلام! 👋 Welcome — if you try a scan, tell us what you find. — Tetracta

The sample reports answer the question I was going to ask, and the answer moves the problem somewhere more interesting.

I wanted to know what the 37th measurement point was. The structure report says it outright: N+1 stations, your 36 layers plus an embedding station at 0. And 37 - 4 = 33, so this post's "33 of 37" is (S - start)/S exactly. Which is what your own rs-1.2 note says when it deprecates spread as "a deterministic function of the start station".

The deprecation is right. I think it reaches further than the report lets it.

Your change-start note says the estimator has a measured detection floor near station 4, that damage confined to stations 0-3 still surfaces at 4, and that the floor is 4 across three families at 0.5B-7B. Put the two notes together and spread is not merely non-independent, it is a constant of the instrument at this scale. Start pinned at 4 gives 89.2% at 36 layers, 86.2% at 28, 84.0% at 24, 76.5% at 16. Nothing about the fine-tune enters.

The floor is visible in your own files. llm-xray-lesion-scans is unmoved at 2ff1f6fb, so I re-ran onset on the six scans: first station where the base-to-tuned |delta| reaches a share s of its own max over depth, all seven ladder levels.

                    s=0.01   s=0.05   s=0.10
znext-v43    L24       0        0        0
van-1b       L16       0       0-1      0-1
qwen2.5-1.5b L28       0       0-1      0-1

21 of 21 rows onset at station 0 at the 1% threshold, and the latest anything reaches at 10% is station 1. Your reported start is 4 on all of them. That is your floor note, measured, on three pairs you published rather than on the controlled test.

Which is why I would not put "the deviation starts at layer 4" on the front card of the Space. On this instrument at 3B, "starts early" cannot come out false.

That leaves the MEDIUM verdict resting on less than it looks like. Its three stated inputs are start (at the floor), spread (a function of start), and behavior-changed at 100%, and your own note says a base-to-chat pairing pushes that last one to 100% on prompt format alone. All three are annotated non-independent inside the same report. What is actually carrying the verdict is N80, 14 of 36, and the band at stations 32-36 with 2.7x enrichment. Your deprecation note points readers from spread to N80, so the schema already knows this. The summary sentence on top is older than the fields that earn it. (Small thing while I am in there: the station-indexing note says percentages use N+1, but N80 and the readout depth both print over 36.)

Now the knowledge half, where one number is out of step with the rest of the report.

You report readout depth the hard way. The marginals are 32.5 and 31.8, a difference of -0.7, and you publish the matched-pair shift of -0.2 instead, restricted to facts that lock in under both models. That is the right statistic and it costs you the bigger number. Same discipline behind "0 of 18 broken, 0 weakened", which is per-fact, not a count that happens to match.

Fabrication avoidance is the one place it is not applied. 13/20 to 18/20 is a difference of marginals on the same 20 items scored twice. The paired test is McNemar on the discordant pairs, and a net +5 has a ceiling:

improved-regressed    exact two-sided p
       5-0                 0.0625
       6-1                 0.1250
       7-2                 0.1797

0.0625 is the best case, and only if not one of the 20 got worse. The first split clearing 0.05 is 6-0. So the Space's front card leads with a +5 that twenty paired items cannot resolve, in a report that computed the paired version for the field directly above it. The two discordant counts are the whole test, and you already have them.

One more, in the fields you ask readers to pin. This post and the Space index both say AUROC 0.878. The knowledge report says 0.877, delta -0.038. A single AUROC on a 20-item probe at a 10/10 split lives on a 1/200 grid, and 0.915 is exactly 183/200. 0.877 and 0.878 are 175.4 and 175.6, neither on it, and a value that renders two ways in the third digit is not a grid point at all. The smallest pair count admitting 0.915 and 0.877 both exactly is 500, which is 20 against 25.

Your own label says "(trajectory)", so I read it as a mean over stations rather than one curve. If that is right then "separation got slightly weaker" compares a mean to a mean, and the item-level resolution is Hanley-McNeil: at 10 and 10 the standard errors are 0.068 and 0.081, and both intervals run past 1.0.

Everything above I could only check because you published raw per-layer KL. The 3B pair ships as a rendered report, not a scan.

You have 11 public models in g1-2026-07, 0.5B to 72B, five families. Has any pair under 32B ever returned a start above 4?

·

Thank you for this — genuinely. This is one of the most valuable pieces of feedback the instrument has received, and exactly the kind of reading we hoped the raw files and notes would make possible.

A first pass on our side already confirms that several of your points land — including the change-start floor question and the paired-test point on fabrication-avoidance — and there is at least one place where we owe you a data-backed clarification rather than a concession. We are now working through the whole review carefully as a team: the front-card wording, the indexing inconsistency, how the verdict fields are presented, and what raw data should ship alongside the rendered reports.

We'll come back to this thread with a point-by-point response and the actual corrections — not just words. Thank you for spending this kind of time on our instrument; reviews like this are how it gets better.

— Tetracta

Start is 4 on all 22 pairs because stations 0 to 3 have no probes.

That is in model-xray-gallery, which you shipped on the 3rd. No rush on the point-by-point. You published the data that answers the question I left open, so I went and answered it instead of asking again.

The answer is no, and wider than I asked

change_start_station across 22 pairs
14 base models, six orgs, 0.5B to 32B
  distinct values: {4}

Not one pair above 4, at any size. Including the eight simulated-quant pairs, which I did not have on the 2nd.

That arm is a positive control, and the field fails it. Simulated int8 touches every layer by construction, stations 0 to 3 included. The scan still reports start 4, with difference_profile at exactly 0.0 in those four cells.

The reason is in the file

contributing_probes[0:4] = [0, 0, 0, 0]     22 of 22
difference_profile[0:4]  = [0.0, 0.0, 0.0, 0.0]

It was never a sensitivity floor. Those stations have no probes assigned. The zero means not measured, not unchanged.

change_start_is_floor: true is the right addition and I want to say so plainly. It is also true on all 22, so as shipped the flag is a constant annotating a constant. It records the problem honestly. It does not yet let a reader tell two scans apart.

spread, now fully determined

spread_fraction == (S - 4) / S      exact on 22 of 22

Start is pinned, so spread is a function of station count alone. Depth in, depth out.

N80 is the live field, on the wrong axis

I reverse-engineered it: the smallest k such that the k largest station differences carry 80% of the total. Top-k over the sorted profile, exact on 22 of 22.

Because it is a top-k, the four dead stations never enter the numerator. They do enter the denominator. So the field has a ceiling that moves with depth:

flat-profile ceiling = 0.8 (S-4) / S
  S=17    0.612
  S=65    0.751
highest n80_fraction anywhere in the gallery: 0.667

Nothing exceeds its own ceiling, which is a good sign for the statistic. But Llama-3.2-1B cannot print above 0.612 while Qwen2.5-32B can reach 0.751, so the raw column is not comparable down the gallery.

Divide the ceiling out and your own trend gets stronger, not weaker:

r(log params, X)          before-after    quant
  n80_fraction               -0.274       -0.394
  share of flat ceiling      -0.447       -0.673

That is the argument for N80 carrying the verdict, improved by the fix rather than damaged by it.

One artifact inside the profile

The probe schedule is identical at every depth, seven tiers of 24, 168 total, and the dead prefix is 4 stations whether the model has 17 or 65:

dead prefix as a share of depth   4/17 = 23.5%    4/65 = 6.2%    3.8x

Within a tier the difference climbs. At every unlock it drops.

depth +1, probe count held:       rises 122 of 132 tiers
depth +1, probe count steps up:   falls 104 of 132 steps

Depth is real and new probes dilute. So the profile is a sawtooth on the unlock schedule rather than a curve. I checked whether that reaches N80 and it barely does: tier-final stations are 32.1% of selections against a 26.0% base rate. Not load-bearing. But it is mechanical, and it is in every file.

behavior_change, at n=22 now

before-after       13 of 14 at exactly 1.0,  min 0.667
simulated-quant     0 of 8  at 1.0,          0.333 to 0.833

The saturation I guessed at from one report holds on fourteen. The quant arm is where that field actually varies, which quietly makes it the more informative half of the gallery.

All of the above is one denominator and one probe schedule. None of it is a rebuild.

The dead prefix is 4 stations at every depth, from 17 to 65. Is that a property of the probes, in that none of the 168 ever locks in before station 4, or is it a fixed offset in the scanner?

·

Dipankar — we rechecked the exact September 3 gallery revision. Your final question has a direct answer: the initial coverage boundary was imposed by the scanner. It was not evidence that the models first changed there. Calling it a measured sensitivity floor was wrong.

  1. Coverage and spread. We reproduced the result across all 22 pairs. The initial unmeasured positions were written as zeros, and spread followed from the reported start and total depth. Neither supports the original location or severity interpretation. The replacement candidate distinguishes “not evaluated” from “no difference detected”; a difference at the first evaluated point leaves the earlier boundary unresolved.

  2. Changing contributors. We reproduced the rising/falling pattern you identified. The replacement calculation holds the contributing set fixed over the evaluated region. A mechanical control and our separate arithmetic recheck on retained raw comparisons agree with that calculation. This addresses the changing-membership effect; it cannot recover the missing prefix or establish causal localization.

  3. N80. Your denominator criticism holds. Our descriptive replacement uses measured coverage and handles ties and zero signal explicitly. We also distinguish an integer count from a fractional depth share. One arithmetic qualification to the flat-profile example: an integer count requires a ceiling, so 17 total positions with 13 measured positions gives 11/17. That does not rescue comparisons made with the old denominator. We are not reinstating the old severity verdict or a cross-model quality ranking.

  4. Output changes and paired outcomes. A base/chat output difference is not a capability improvement. For the original fabricated-name items, the retained paired transitions are 6 in one direction and 1 in the other: exact two-sided McNemar p = 0.125. The old scoring counted avoidance of repeating a fabricated name; it did not validate fabrication avoidance. The earlier improvement interpretation remains withdrawn.

  5. AUROC. The archived first-report inputs contain 20 known and 20 fabricated items. The stored value is 0.8775, which is compatible with that pair count; the HTML and post displayed it differently. We cannot reproduce that first trajectory AUROC from its original item scores because those scores are absent from the retained record. Later scans are not a substitute. We have not restored the Knowledge or separation claim.

We have a separate early-coverage candidate with bounded controls on one trained small model, including recorded misses at small changes. That is research evidence, not a repair of the historical scans or validation across arbitrary fine-tunes. General onset localization and added usefulness over simpler comparisons remain open.

The updated VG1 application has been deployed with a narrower scope than the original post. Customer scan-to-report acceptance is still pending. The calculation changes above are in this release; the wider measurement questions remain open.

Historical gallery revision · Dated correction

Your integer qualification is right and I had it wrong.

n80_stations is a count, so the flat-profile ceiling is ceil(0.8 x measured)/S, not 0.8 x measured/S. At S=17 that is ceil(10.4) = 11, so 11/17 = 0.6471, not the 0.6118 I posted.

Re-ran the whole gallery at 50ae1ec with the corrected form:

S    measured   continuous   integer
17     13         0.6118     11/17 = 0.6471
25     21         0.6720     17/25 = 0.6800
29     25         0.6897     20/29 = 0.6897
33     29         0.7030     24/33 = 0.7273
37     33         0.7135     27/37 = 0.7297
49     45         0.7347     36/49 = 0.7347
65     61         0.7508     49/65 = 0.7538

It only bites on 14 of the 22 pairs. At S=29 and S=49 the two forms are identical, because 0.8 x 25 and 0.8 x 45 are already integers. Nothing exceeds either ceiling, so that part survives.

The correction makes the statistic look better, not worse.

r(log params, X)         continuous ceiling   integer ceiling
  before-after (n=14)         -0.447             -0.454
  simulated-quant (n=8)       -0.673             -0.745

Raw n80_fraction is untouched at -0.274 and -0.394. Every step of this has moved the same direction.

And there is a version of it that never touches the denominator at all.

Each simulated-quant pair shares its station count with the before-after pair it was built from. S is identical inside the pair, so the ceiling divides out and the comparison is immune to this whole dispute:

base                             S    BA n80   QT n80
SmolLM2-1.7B-Instruct           25      13       15
Qwen2.5-0.5B-Instruct           25      15       16
Qwen2.5-1.5B-Instruct           29      13       18
Qwen2.5-7B-Instruct             29      14       17
Llama-3.1-8B-Instruct           33      21       22
Mistral-7B-Instruct-v0.3        33      22       22
Qwen2.5-14B-Instruct            49      21       30
Qwen2.5-32B-Instruct            65      26       35

7 up, 0 down, 1 exact tie. Sign test on the 7 non-ties, two-sided p = 0.0156.

The positive control spreads wider than the fine-tune it was built from, every single time it moves at all. That is the one N80 claim that holds with the prefix missing, the denominator disputed, and my own arithmetic wrong.

Your other two check out. 0.8775 is exactly 351/400, and 400 is the smallest denominator that produces it, so 20 by 20 is the tightest pair count consistent with the stored value. McNemar at 6 and 1 is 2 x P(X <= 1) over Bin(7, 0.5) = 16/128 = 0.125.

Mistral is the tie, 22 and 22 at S=33. Does the replacement statistic separate that pair, or does it stay tied there too?