Studies of what fine-tuning does to a language model often summarise the weight update ΔW by its rank. We compare the rank measures used for this against the same measures on a random matrix of the same shape, and against two harder references: the pretrained weights, and matched fine-tunes without alignment content. Measures that count directions put our fine-tuning updates only a little below noise; stable rank, computed from the same singular values, puts them far below. Both are right: an update has a few strong directions on top of a long tail. The pattern holds for thirteen released pairs up to 8B parameters, and it is not a mark of alignment: with training held fixed, instruction data does not stand out from Wikipedia or code, DPO gives the same update whether its preference labels are real or half swapped at random (one model, modest preference strength), and scrambled text gives the most concentrated update of all. Applied to a recent claim that post-training is superficial because the effective rank of the weights barely changes, the baselines show that a random update of the same size leaves that rank almost unchanged while wrecking the model, and that an edit built on the effective rank of the update has no measurable effect in our tests. Rank measures of weight updates need a noise baseline, and claims about alignment need a control without alignment content.
Figures & tables
model
matrix
threshold
eRank
90% energy
particip.
stable
top-1 energy
Qwen2.5-0.5B
SFT update
0.973
0.816
0.541
0.381
0.097
4.2%
wikitext update
0.972
0.810
0.531
0.365
0.093
4.0%
code update
0.975
0.817
0.543
0.374
0.094
3.8%
shuffled-words update
0.941
0.745
0.440
0.202
0.042
9.0%
DPO update
0.966
0.810
0.536
0.295
0.053
5.8%
swapped-DPO update
0.967
0.811
0.537
0.304
0.055
5.7%
Table 1: Rank measures as a fraction of the maximum rank, and the share of energy in the top direction, averaged over all attention and MLP matrices. “Noise” is the random-init pair; “pretrained W ” is the base model’s own weights. The DPO updates are measured from the SFT model they start from.
Figure 1: How far below noise each measure puts each update, 1−update/noise , with 95% layer-bootstrap intervals. Measures are ordered by how much weight they give to the top directions. The gap grows from a few percent for the threshold count to 78–94% for stable rank, and to 90–97% for the shuffled-words updates.
Figure 2: Where the energy sits, averaged over the 168 matrices of Qwen2.5-0.5B. Left: share of energy in the top fraction of directions. Right: singular values relative to the largest. Updates put much more energy in their top directions than noise does, then decay slowly over a long tail. The pretrained weights (dashed) sit between the updates and noise.
difference
Qwen2.5-0.5B
SmolLM2-360M
SFT − wikitext
+0.004 ( −0.001 , +0.010 )
+0.005 ( +0.003 , +0.006 )
SFT − code
+0.003 ( −0.000 , +0.006 )
−0.009 ( −0.011 , −0.008 )
code − wikitext
+0.002 ( −0.004 , +0.007 )
+0.014 ( +0.012 , +0.016 )
shuffled words − SFT
−0.054 ( −0.062 , −0.047 )
−0.016 ( −0.018 , −0.014 )
code, steps matched − code
+0.020 ( +0.018 , +0.023 )
+0.007 ( +0.007 , +0.008 )
swapped DPO − DPO
+0.002 ( +0.000 , +0.004 )
–
Table 2: Differences in stable rank between runs on the same model, paired matrix by matrix, with 95% layer-bootstrap intervals. The intervals describe the spread over layers within one run, not between training runs; “second seed” repeats a run with a different seed and data sample. “Steps matched” trains on code for as many optimizer steps as SFT, which is 2.5–2.7 times more code tokens.
Figure 3: Released updates (blue) against a Gaussian matrix of the same shape (grey), in three groups: base/instruct releases, the OLMo 2 post-training stages, and code/math specialists. Left: the threshold count (axis starts at 0.85). Right: stable rank.
update
threshold
noise
above floor
stable rank
noise
stable w/o top
SmolLM2-135M instruct
0.971
0.996
96%
0.086
0.354
0.119
SmolLM2-360M instruct
0.964
0.996
95%
0.039
0.356
0.059
Qwen2.5-0.5B instruct
0.990
0.996
97%
0.280
0.434
0.314
Qwen3-0.6B
0.989
0.996
99%
0.124
0.342
0.145
Qwen2.5-1.5B instruct
0.969
0.996
78%
0.051
0.432
0.073
SmolLM2-1.7B instruct
0.959
0.993
91%
0.075
0.336
0.090
Table 3: Released pairs, means over matrices. “Above floor” is the share of the update’s singular values larger than the largest singular value of the simulated bf16 rounding error: directions that rounding alone cannot produce (§ 2 ). It is not computed (–) for OLMo 2 base to SFT, whose base, a mid-training checkpoint, is stored in fp32. The last column drops the top direction, to check that one outlier does not drive the result.
Figure 4: Left: size of the change in the effective rank of the full weight matrix W , ∣ΔeRank(W)∣/eRank(W) averaged over matrices, for the real base-to-instruct update (blue) and a random update of the same Frobenius norm (grey). Right: perplexity on held-out wikitext of Qwen3-0.6B base, unchanged, after a random update of the same size as its real post-training update (Gaussian, or with the real update’s singular values), and after the real update, which gives the instruct model. The numbers above the bars give the size of the change in eRank( W ) for each update, as in the left panel.
model
accuracy
difference
∣ change ∣ in eRank( W )
base
59.5
–
–
base + Gaussian update, draw 1
4.1
−55.4 ( −58.2 , −52.7 )
0.50%
base + Gaussian update, draw 2
4.8
−54.7 ( −57.5 , −52.2 )
–
base + real singular values, random directions
5.8
−53.8 ( −56.6 , −50.9 )
0.48%
instruct (= base + real update)
64.5
–
0.13%
instruct + Gaussian update
11.9
−52.6 ( −55.3 , −49.9 )
–
Table 4: GSM8K accuracy, in percent (greedy, all 1,319 test problems), of Qwen3-0.6B with a random update of the same size as its real post-training update, added to every attention and MLP matrix. Each pair uses the same prompt and token limit: the base model an 8-shot plain-text prompt, the instruct model its chat template. Differences in points with 95% paired bootstrap intervals.
Figure 5: GSM8K pass@ k for Qwen3-0.6B (non-thinking mode) with tail edits and with uniform scaling of the whole update. Eight samples per problem, the same sampling seed per problem for every variant. Left: first 300 test problems, main variants (every variant is in Table 15 ). Right: all 1,319 (Table 5 ).
edit
unscaled
pass@1
pass@8
answered
Δ pass@1
Δ pass@8
none
100%
62.3
85.1
97.4%
–
–
tail ×0.2 , eRank cutoff (Timber)
98.9%
62.3
85.3
97.1%
−0.0 ( −0.8 , +0.8 )
+0.2 ( −1.4 , +1.8 )
tail ×0.5 , eRank cutoff (Timber)
98.9%
63.1
85.9
97.1%
+0.7 ( −0.0 , +1.6 )
+0.8 ( −0.6 , +2.3 )
tail ×0.5 , stable-rank cutoff
41.4%
62.9
86.9
96.0%
+0.6 ( −0.5 , +1.7 )
+1.8 ( +0.2 , +3.5 )
whole update ×0.75 (same size)
0%
65.8
87.8
96.4%
+3.4 ( +2.4 , +4.5 )
+2.7 ( +1.1 , +4.2 )
Table 5: Edits of the Qwen3-0.6B update on all 1,319 GSM8K test problems; pass@ k in percent. “Unscaled” is the share of the update’s energy the edit leaves at full strength (uniform scaling shrinks every direction by the same factor); “answered” is the share of samples with a final boxed answer; “same size” means scaled to the size of the stable-rank edit. Differences from the unedited model in points, with 95% paired bootstrap intervals over problems, not corrected for multiple comparisons.
edit
accuracy
Δ accuracy
pass@4
Δ pass@4
none
25.9
–
46.6
–
tail ×0.2 , eRank cutoff (Timber)
26.9
+0.9 ( −2.1 , +4.0 )
46.0
−0.6 ( −5.9 , +4.8 )
tail ×0.5 , eRank cutoff (Timber)
26.4
+0.4 ( −2.5 , +3.5 )
47.5
+0.9 ( −4.2 , +6.4 )
tail ×0.8 , eRank cutoff (Timber)
26.9
+0.9 ( −2.0 , +3.9 )
47.0
+0.4 ( −4.8 , +5.6 )
tail ×0.2 , stable-rank cutoff
21.3
−4.6 ( −9.3 , +0.2 )
48.0
+1.4 ( −6.4 , +9.4 )
whole update, scaled to the stable-rank edit’s size
22.9
−3.1 ( −7.1 , +0.9 )
54.0
+7.5 ( +0.5 , +14.3 )
Table 6: The same edits on GPQA-Diamond ( Rein et al., 2024 ) , Wu et al.’s benchmark, 198 questions, non-thinking mode with their sampling settings. “Accuracy” is the mean over samples (their Mean@ k ), in percent, as is pass@4; eight samples per question for the unedited model, four for each edit. Differences in points with 95% paired bootstrap intervals over questions.
Appendix figures & tables10 assets
Supplementary material from the paper’s appendix.
Appendix
setting
value
weights / compute precision
fp32 master weights, bf16 autocast
optimizer
8-bit AdamW, learning rate 2×10−5 , no weight decay
schedule
cosine, 3% warmup, 3 epochs, gradient clipping at 1.0
batch
1 sequence × 16 accumulation steps
sequence length
512 tokens
embeddings
frozen (tied with the output head; not analysed)
Appendix
Table 7: Settings shared by all our fine-tunes. Each language-model run trains on the same number of tokens as the SFT run of the same model, counted after truncation. DPO uses the same precision, memory settings and batch, with the changes listed at the bottom.
model
run
steps
loss
∥ΔW∥F
stable rank
stable w/o top
hours
Qwen2.5-0.5B
SFT
1,840
1.00
10.4
0.097
0.126
2.8
SFT, seed 2
1,840
–
10.5
0.096
0.126
–
wikitext
1,910
2.23
12.1
0.093
0.122
2.8
wikitext, seed 2
1,910
2.24
12.0
0.092
0.121
2.7
code
680
1.11
6.3
0.094
0.123
1.3
code, seed 2
670
1.12
6.3
0.094
0.122
1.3
Appendix
Table 8: Every fine-tune. Steps are optimizer steps (rounded to 10); loss is the mean training loss; ∥ΔW∥F is over all attention and MLP matrices. The second SFT seed was interrupted and resumed from step 1,600 with its optimizer and scheduler state, so its logged mean loss covers only the last steps and is not shown.
model
matrix
0.01σ1
0.05σ1
0.1σ1
Qwen2.5-0.5B
SFT update
0.973
0.889
0.787
wikitext update
0.972
0.886
0.775
code update
0.975
0.895
0.799
shuffled-words update
0.941
0.752
0.530
noise
0.996
0.982
0.964
pretrained W
0.976
0.913
0.851
Appendix
Table 9: The threshold count at three cutoffs. At 0.01σ1 every update looks almost like noise; at 0.1σ1 the gap is large. The verdict depends on an arbitrary choice.
matrix
shape
predicted
random-init pair
q , o
896×896
0.250
0.252, 0.251
k , v
128×896
0.527
0.536, 0.535
gate , up
4864×896
0.490
0.492, 0.492
down
896×4864
0.490
0.493
Appendix
Table 10: Stable rank of the random-init pair against the prediction mn/(m+n)2/r for a Gaussian matrix of the same shape, Qwen2.5-0.5B, mean over layers.
Figure 6: How far below noise each update is, 1−Rα(update)/Rα(noise) as means over matrices, along the Rényi family from α=1/4 to α=∞ (stable rank, squares). The gap grows with the order and levels off from about α=8 .
model
matrix
q
k
v
o
gate
up
down
Qwen2.5-0.5B
SFT update
0.032
0.064
0.251
0.057
0.064
0.072
0.139
wikitext update
0.031
0.072
0.227
0.057
0.065
0.085
0.112
code update
0.031
0.070
0.243
0.058
0.057
0.073
0.127
shuffled-words update
0.011
0.043
0.124
0.021
0.023
0.026
0.048
noise
0.252
0.536
0.535
0.251
0.492
0.492
0.493
pretrained W
0.058
0.212
0.453
0.078
0.071
0.242
0.135
Appendix
Table 11: Stable rank (fraction of maximum rank) by matrix type.
model
update
first quarter
second
third
last quarter
Qwen2.5-0.5B
SFT
0.094
0.099
0.103
0.091
wikitext
0.086
0.100
0.104
0.080
code
0.091
0.097
0.104
0.084
shuffled words
0.055
0.039
0.034
0.041
SmolLM2-360M
SFT
0.023
0.027
0.029
0.021
wikitext
0.019
0.024
0.023
0.015
Appendix
Table 12: Stable rank by quarter of the network.
update
particip. ratio
noise
above edge
rounding share
∥ΔW∥F/∥W∥F
zero entries
SmolLM2-135M instruct
0.321
0.667
30
28%
8.1%
2.5%
SmolLM2-360M instruct
0.239
0.668
46
10%
7.6%
2.7%
Qwen2.5-0.5B instruct
0.657
0.755
22
76%
7.8%
2.2%
Qwen3-0.6B
0.442
0.654
72
15%
12.7%
1.5%
Qwen2.5-1.5B instruct
0.299
0.753
100
94%
1.2%
14.0%
SmolLM2-1.7B instruct
0.375
0.629
140
45%
6.2%
3.1%
Appendix
Table 13: More on the released pairs. “Particip. ratio”: the participation ratio, next to its value for a Gaussian matrix of the same shape. “Above edge”: the number of singular values above the largest one such a Gaussian matrix would have (mean per matrix). “Rounding share”: the number of singular values of the simulated bf16 rounding error above 0.01σ1 of the update, as a share of the update’s threshold count; a loose upper bound on how much of the count rounding could explain, as a ratio of means over matrices (compare the “above floor” column of Table 3 ). ∥ΔW∥F/∥W∥F : the size of the update relative to the base weights. “Zero entries”: the share of entries of ΔW that are exactly zero, the direct trace of rounding.
pair
Qwen2.5-0.5B
SmolLM2-360M
SFT vs SFT, seed 2
0.32 (0.30, 0.33)
0.51 (0.50, 0.52)
wikitext vs wikitext, seed 2
0.30 (0.29, 0.31)
0.49 (0.47, 0.52)
code vs code, seed 2
0.26 (0.25, 0.27)
0.34 (0.33, 0.36)
code vs code, steps matched
0.37 (0.36, 0.39)
0.54 (0.53, 0.55)
SFT vs wikitext
0.22 (0.21, 0.23)
0.13 (0.13, 0.14)
SFT vs code
0.20 (0.19, 0.21)
0.12 (0.12, 0.12)
Appendix
Table 14: Overlap of the top-16 left singular subspaces of two updates, mean over matrices, with 95% layer-bootstrap intervals.
edit
pass@1
pass@8
answered
Δ pass@1
Δ pass@8
none
63.4
84.7
96.5%
–
–
tail ×0 , eRank cutoff
63.9
87.7
96.7%
+0.5 ( −1.3 , +2.3 )
+3.0 ( −0.3 , +6.3 )
tail ×0.2 , eRank cutoff
64.0
85.7
96.8%
+0.5 ( −1.3 , +2.4 )
+1.0 ( −2.0 , +4.0 )
tail ×0.5 , eRank cutoff
64.7
88.0
96.8%
+1.3 ( −0.5 , +3.0 )
+3.3 ( +0.7 , +6.3 )
tail ×0 , stable-rank cutoff
59.3
83.0
90.6%
−4.2 ( −6.9 , −1.4 )
−1.7 ( −5.3 , +2.0 )
tail ×0.5 , stable-rank cutoff
64.5
87.3
95.1%
+1.1 ( −1.1 , +3.3 )
+2.7 ( −1.0 , +6.3 )
Appendix
Table 15: All edit variants on the first 300 GSM8K test problems, pass@ k in percent. Differences from the unedited model in points, with 95% paired bootstrap intervals, not corrected for the fourteen comparisons. “Answered” is the share of samples with a final boxed answer. “Uniform” scales the whole update, per matrix, to the size of the named tail edit.