๐Ÿ”ฌ BitBlame โ€” dynamic quantization forensics

Which layers lose accuracy when a model is quantized? BitBlame measures per-unit quantization sensitivity with confidence intervals, and turns the measurement into a mixed-precision GGUF recipe. This page shows the preloaded Phase B audit on SmolLM2-135M โ€” no live run.

Honesty block โ€” read this before the headline numbers.

Per-unit blame โ€” SmolLM2-135M

Per-unit blame scores with 95% BCa confidence intervals

Top-3 units (embed + blk.29 + blk.11) = 57.9% of total measured sensitivity; embedding alone 32.0%. Split-half rank stability rho = 0.9754; 31/31 units pass the significance gate (null-floor max CI-high = 0.00307). Screen-vs-exact ranking agreement: Spearman rho = 0.9286 at 4-bit (top-8).

#unitS_u95% CIsharegatealloc
1embed0.3674[0.3471, 0.3927]32.0%yesQ5_K
2blk.290.1604[0.1377, 0.2286]14.0%yesQ6_K
3blk.110.1366[0.1276, 0.1434]11.9%yesQ8_0
4blk.280.0652[0.0585, 0.0739]5.7%yesQ6_K
5blk.20.0503[0.0413, 0.0612]4.4%yesQ6_K
6blk.90.0351[0.0267, 0.0466]3.1%yesQ5_K
7blk.270.0229[0.0210, 0.0253]2.0%yesQ5_K
8blk.190.0182[0.0173, 0.0192]1.6%yesQ5_K
9blk.00.0174[0.0153, 0.0202]1.5%yesQ5_K
10blk.180.0167[0.0156, 0.0182]1.5%yesQ5_K
11blk.230.0160[0.0143, 0.0179]1.4%yesQ5_K
12blk.30.0153[0.0131, 0.0184]1.3%yesQ4_K
13blk.160.0149[0.0137, 0.0160]1.3%yesQ4_K
14blk.120.0142[0.0132, 0.0153]1.2%yesQ4_K
15blk.220.0139[0.0130, 0.0152]1.2%yesQ4_K
16blk.210.0136[0.0126, 0.0146]1.2%yesQ4_K
17blk.200.0133[0.0123, 0.0157]1.2%yesQ4_K
18blk.10.0132[0.0112, 0.0155]1.2%yesQ4_K
19blk.150.0130[0.0119, 0.0139]1.1%yesQ4_K
20blk.140.0127[0.0115, 0.0142]1.1%yesQ2_K
21blk.130.0126[0.0115, 0.0137]1.1%yesQ2_K
22blk.170.0122[0.0108, 0.0160]1.1%yesQ2_K
23blk.240.0118[0.0111, 0.0126]1.0%yesQ2_K
24blk.100.0118[0.0107, 0.0131]1.0%yesQ2_K
25blk.80.0115[0.0105, 0.0128]1.0%yesQ2_K
26blk.40.0107[0.0089, 0.0134]0.9%yesQ2_K
27blk.50.0104[0.0090, 0.0124]0.9%yesQ2_K
28blk.70.0098[0.0089, 0.0112]0.9%yesQ2_K
29blk.60.0095[0.0085, 0.0112]0.8%yesQ2_K
30blk.260.0086[0.0082, 0.0091]0.8%yesQ2_K
31blk.250.0076[0.0072, 0.0083]0.7%yesQ2_K

The measured recipe

Exact-DP knapsack over 6 real GGUF quant types, emitted as llama-quantize --tensor-type overrides. Resulting GGUF: 94,373,920 B vs Q4_K_M baseline 105,453,856 B (ratio 0.8949 โ€” 10.5% smaller). Note: the output.weight=Q5_K line is a no-op on this tied-embedding model (no such tensor exists); unmentioned tensors fall back to Q4_K_M. Full recipe file: recipe.sh in the dataset.

#!/bin/sh
# BitBlame recipe โ€” measured-sensitivity-driven GGUF quantization
# Generated per METHODOLOGY.md ยง7.4 (spec v1.0).
# Unmentioned tensors fall back to the base type.
set -e

# 1) importance matrix on the calibration mix (ยง5.1)
llama-imatrix -m model-f16.gguf -f calib.txt -o imatrix.dat

# 2) quantize with per-tensor overrides (measured allocation)
llama-quantize --imatrix imatrix.dat \
  --tensor-type 'blk.0.attn_q.weight=Q5_K' \
  --tensor-type 'blk.0.attn_k.weight=Q5_K' \
  --tensor-type 'blk.0.attn_v.weight=Q5_K' \
  --tensor-type 'blk.0.attn_output.weight=Q5_K' \
  --tensor-type 'blk.0.ffn_gate.weight=Q5_K' \
  --tensor-type 'blk.0.ffn_up.weight=Q5_K' \
  --tensor-type 'blk.0.ffn_down.weight=Q5_K' \
  --tensor-type 'blk.10.attn_q.weight=Q2_K' \
  --tensor-type 'blk.10.attn_k.weight=Q2_K' \
  --tensor-type 'blk.10.attn_v.weight=Q2_K' \
  --tensor-type 'blk.10.attn_output.weight=Q2_K' \
  --tensor-type 'blk.10.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.10.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.10.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.11.attn_q.weight=Q8_0' \
  --tensor-type 'blk.11.attn_k.weight=Q8_0' \
  --tensor-type 'blk.11.attn_v.weight=Q8_0' \
  --tensor-type 'blk.11.attn_output.weight=Q8_0' \
  --tensor-type 'blk.11.ffn_gate.weight=Q8_0' \
  --tensor-type 'blk.11.ffn_up.weight=Q8_0' \
  --tensor-type 'blk.11.ffn_down.weight=Q8_0' \
  --tensor-type 'blk.13.attn_q.weight=Q2_K' \
  --tensor-type 'blk.13.attn_k.weight=Q2_K' \
  --tensor-type 'blk.13.attn_v.weight=Q2_K' \
  --tensor-type 'blk.13.attn_output.weight=Q2_K' \
  --tensor-type 'blk.13.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.13.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.13.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.14.attn_q.weight=Q2_K' \
  --tensor-type 'blk.14.attn_k.weight=Q2_K' \
  --tensor-type 'blk.14.attn_v.weight=Q2_K' \
  --tensor-type 'blk.14.attn_output.weight=Q2_K' \
  --tensor-type 'blk.14.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.14.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.14.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.17.attn_q.weight=Q2_K' \
  --tensor-type 'blk.17.attn_k.weight=Q2_K' \
  --tensor-type 'blk.17.attn_v.weight=Q2_K' \
  --tensor-type 'blk.17.attn_output.weight=Q2_K' \
  --tensor-type 'blk.17.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.17.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.17.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.18.attn_q.weight=Q5_K' \
  --tensor-type 'blk.18.attn_k.weight=Q5_K' \
  --tensor-type 'blk.18.attn_v.weight=Q5_K' \
  --tensor-type 'blk.18.attn_output.weight=Q5_K' \
  --tensor-type 'blk.18.ffn_gate.weight=Q5_K' \
  --tensor-type 'blk.18.ffn_up.weight=Q5_K' \
  --tensor-type 'blk.18.ffn_down.weight=Q5_K' \
  --tensor-type 'blk.19.attn_q.weight=Q5_K' \
  --tensor-type 'blk.19.attn_k.weight=Q5_K' \
  --tensor-type 'blk.19.attn_v.weight=Q5_K' \
  --tensor-type 'blk.19.attn_output.weight=Q5_K' \
  --tensor-type 'blk.19.ffn_gate.weight=Q5_K' \
  --tensor-type 'blk.19.ffn_up.weight=Q5_K' \
  --tensor-type 'blk.19.ffn_down.weight=Q5_K' \
  --tensor-type 'blk.2.attn_q.weight=Q6_K' \
  --tensor-type 'blk.2.attn_k.weight=Q6_K' \
  --tensor-type 'blk.2.attn_v.weight=Q6_K' \
  --tensor-type 'blk.2.attn_output.weight=Q6_K' \
  --tensor-type 'blk.2.ffn_gate.weight=Q6_K' \
  --tensor-type 'blk.2.ffn_up.weight=Q6_K' \
  --tensor-type 'blk.2.ffn_down.weight=Q6_K' \
  --tensor-type 'blk.23.attn_q.weight=Q5_K' \
  --tensor-type 'blk.23.attn_k.weight=Q5_K' \
  --tensor-type 'blk.23.attn_v.weight=Q5_K' \
  --tensor-type 'blk.23.attn_output.weight=Q5_K' \
  --tensor-type 'blk.23.ffn_gate.weight=Q5_K' \
  --tensor-type 'blk.23.ffn_up.weight=Q5_K' \
  --tensor-type 'blk.23.ffn_down.weight=Q5_K' \
  --tensor-type 'blk.24.attn_q.weight=Q2_K' \
  --tensor-type 'blk.24.attn_k.weight=Q2_K' \
  --tensor-type 'blk.24.attn_v.weight=Q2_K' \
  --tensor-type 'blk.24.attn_output.weight=Q2_K' \
  --tensor-type 'blk.24.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.24.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.24.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.25.attn_q.weight=Q2_K' \
  --tensor-type 'blk.25.attn_k.weight=Q2_K' \
  --tensor-type 'blk.25.attn_v.weight=Q2_K' \
  --tensor-type 'blk.25.attn_output.weight=Q2_K' \
  --tensor-type 'blk.25.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.25.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.25.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.26.attn_q.weight=Q2_K' \
  --tensor-type 'blk.26.attn_k.weight=Q2_K' \
  --tensor-type 'blk.26.attn_v.weight=Q2_K' \
  --tensor-type 'blk.26.attn_output.weight=Q2_K' \
  --tensor-type 'blk.26.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.26.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.26.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.27.attn_q.weight=Q5_K' \
  --tensor-type 'blk.27.attn_k.weight=Q5_K' \
  --tensor-type 'blk.27.attn_v.weight=Q5_K' \
  --tensor-type 'blk.27.attn_output.weight=Q5_K' \
  --tensor-type 'blk.27.ffn_gate.weight=Q5_K' \
  --tensor-type 'blk.27.ffn_up.weight=Q5_K' \
  --tensor-type 'blk.27.ffn_down.weight=Q5_K' \
  --tensor-type 'blk.28.attn_q.weight=Q6_K' \
  --tensor-type 'blk.28.attn_k.weight=Q6_K' \
  --tensor-type 'blk.28.attn_v.weight=Q6_K' \
  --tensor-type 'blk.28.attn_output.weight=Q6_K' \
  --tensor-type 'blk.28.ffn_gate.weight=Q6_K' \
  --tensor-type 'blk.28.ffn_up.weight=Q6_K' \
  --tensor-type 'blk.28.ffn_down.weight=Q6_K' \
  --tensor-type 'blk.29.attn_q.weight=Q6_K' \
  --tensor-type 'blk.29.attn_k.weight=Q6_K' \
  --tensor-type 'blk.29.attn_v.weight=Q6_K' \
  --tensor-type 'blk.29.attn_output.weight=Q6_K' \
  --tensor-type 'blk.29.ffn_gate.weight=Q6_K' \
  --tensor-type 'blk.29.ffn_up.weight=Q6_K' \
  --tensor-type 'blk.29.ffn_down.weight=Q6_K' \
  --tensor-type 'blk.4.attn_q.weight=Q2_K' \
  --tensor-type 'blk.4.attn_k.weight=Q2_K' \
  --tensor-type 'blk.4.attn_v.weight=Q2_K' \
  --tensor-type 'blk.4.attn_output.weight=Q2_K' \
  --tensor-type 'blk.4.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.4.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.4.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.5.attn_q.weight=Q2_K' \
  --tensor-type 'blk.5.attn_k.weight=Q2_K' \
  --tensor-type 'blk.5.attn_v.weight=Q2_K' \
  --tensor-type 'blk.5.attn_output.weight=Q2_K' \
  --tensor-type 'blk.5.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.5.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.5.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.6.attn_q.weight=Q2_K' \
  --tensor-type 'blk.6.attn_k.weight=Q2_K' \
  --tensor-type 'blk.6.attn_v.weight=Q2_K' \
  --tensor-type 'blk.6.attn_output.weight=Q2_K' \
  --tensor-type 'blk.6.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.6.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.6.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.7.attn_q.weight=Q2_K' \
  --tensor-type 'blk.7.attn_k.weight=Q2_K' \
  --tensor-type 'blk.7.attn_v.weight=Q2_K' \
  --tensor-type 'blk.7.attn_output.weight=Q2_K' \
  --tensor-type 'blk.7.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.7.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.7.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.8.attn_q.weight=Q2_K' \
  --tensor-type 'blk.8.attn_k.weight=Q2_K' \
  --tensor-type 'blk.8.attn_v.weight=Q2_K' \
  --tensor-type 'blk.8.attn_output.weight=Q2_K' \
  --tensor-type 'blk.8.ffn_gate.weight=Q2_K' \
  --tensor-type 'blk.8.ffn_up.weight=Q2_K' \
  --tensor-type 'blk.8.ffn_down.weight=Q2_K' \
  --tensor-type 'blk.9.attn_q.weight=Q5_K' \
  --tensor-type 'blk.9.attn_k.weight=Q5_K' \
  --tensor-type 'blk.9.attn_v.weight=Q5_K' \
  --tensor-type 'blk.9.attn_output.weight=Q5_K' \
  --tensor-type 'blk.9.ffn_gate.weight=Q5_K' \
  --tensor-type 'blk.9.ffn_up.weight=Q5_K' \
  --tensor-type 'blk.9.ffn_down.weight=Q5_K' \
  --tensor-type 'token_embd.weight=Q5_K' \
  --tensor-type 'output.weight=Q5_K' \
  model-f16.gguf model-bitblame.gguf Q4_K_M

echo "recipe done -> model-bitblame.gguf"

Run it yourself: pip install git+https://github.com/habib-analyst/bitblame.git then bitblame scan / probes / recipe / validate / report (see the repo README Quickstart).

Audit results โ€” pre-registered paired test (n = 250)

ComparisonRecipe vs Q4_K_M baseline
Accuracy11.60% = 11.60%
Mean paired delta0.00 pp (15 wins, 15 losses, 220 ties)
95% BCa CI[-4.8 pp, +4.0 pp], p = 0.5338
VerdictNO_SIGNIFICANT_DIFFERENCE; non-inferiority at 0.5 pp margin FAILS
Size94,373,920 B vs 105,453,856 B โ€” 10.5% smaller, size gate (≤ 1.01x) passes
Closed loopHarness exit 0; 272/272 tensor types verified, 0 mismatches
Optimizer bit-cost modelReproduces 272/272 tensor types and stored bytes exactly (0.0000% error) on both GGUFs
imatrix agreementSpearman rho = 0.2908 (p = 0.119, n = 30) โ€” BELOW rho >= 0.5 bar; corroboration FAILS

Per-category paired deltas (recipe โˆ’ baseline)

categorynFP16Q4_K_Mrecipedelta95% CIverdict
copy200.0%0.0%0.0%+0.00 pp[+0.0, +0.0] ppNO_SIGNIFICANT_DIFFERENCE
gsm8k601.7%3.3%1.7%-1.67 pp[-10.0, +0.0] ppNO_SIGNIFICANT_DIFFERENCE
humaneval300.0%0.0%0.0%+0.00 pp[+0.0, +0.0] ppNO_SIGNIFICANT_DIFFERENCE
mmlu10028.0%20.0%25.0%+5.00 pp[-5.0, +14.0] ppNO_SIGNIFICANT_DIFFERENCE
needle407.5%17.5%7.5%-10.00 pp[-27.5, -5.0] ppSIGNIFICANT_REGRESSION

Needle note: the bootstrap mechanically flags SIGNIFICANT_REGRESSION, but recipe-vs-reference is 0 (both 3/40) โ€” the baseline scored above the FP16 reference by chance.

Methodology (summary)

  1. Stage 0 โ€” cache FP16 logits (1 forward pass per calibration seq).
  2. Stage 1 โ€” mock-noise LOLO scan. Perturb one unit's weights with quantization-calibrated noise; mean per-token KL vs FP16 reference. Bootstrap BCa CIs (B=2000), null-floor significance gate, split-half reliability gate.
  3. Stage 2 โ€” exact top-8 verification. Re-measure top units with exact quantize→dequantize at 3/4/6 bits; power-law fits. Screen-vs-exact agreement gate rho >= 0.7.
  4. Stage 3 โ€” behavioral probe battery. 250 items (100 MMLU + 60 GSM8K + 30 HumanEval + 40 needle + 20 copy), FP16 vs baseline-quant, paired items.
  5. Stage 4 โ€” bit-budget optimizer. Significance-gated exact-DP multiple-choice knapsack over 6 real GGUF quant types → llama-quantize overrides + imatrix guidance.
  6. Stage 5 โ€” closed-loop validation. Re-quantize with real llama-quantize, re-measure, pre-registered paired-bootstrap verdict.

Limitations

Full spec: METHODOLOGY.md in the repo. Full numbers: P2_REPORT.md in the repo.