|
| 1 | +# Model Validation |
| 2 | + |
| 3 | +An operational validation suite for OneComp's end-to-end workflow |
| 4 | +(quantize → save → load → inference) across a variety of model |
| 5 | +architectures and sizes. Each subdirectory exercises one workflow |
| 6 | +configuration; what is exercised varies per subdirectory and is listed |
| 7 | +below. |
| 8 | + |
| 9 | +Sanity checks reported here: |
| 10 | + |
| 11 | +- Perplexity on `wikitext-2-raw-v1`, only as a check that the quantized |
| 12 | + model is not broken — **not** an accuracy benchmark. |
| 13 | +- Greedy generation from a saved + reloaded model, only as a check |
| 14 | + that the load + inference path runs without errors. |
| 15 | + |
| 16 | +## At a Glance |
| 17 | + |
| 18 | +### Quantization |
| 19 | + |
| 20 | +Status legend (quantization step only): |
| 21 | + |
| 22 | +- **OK** — quantize runs end-to-end and the resulting (quantized, or |
| 23 | + dequantized for recipes that don't have a quantized-inference path |
| 24 | + yet) model passes the PPL sanity check. |
| 25 | +- **OK\*** — runs, but PPL is somewhat worse than expected for the |
| 26 | + recipe; worth a closer look. |
| 27 | +- **NG** — runs, but PPL is clearly broken. |
| 28 | +- **pending** — not yet executed. |
| 29 | + |
| 30 | +| Model | GPTQ | QEP+GPTQ | AutoBit | AutoBit+QEP | JointQ | |
| 31 | +|---|:---:|:---:|:---:|:---:|:---:| |
| 32 | +| TinyLlama-1.1B | OK | OK | OK | OK | OK | |
| 33 | +| gemma-4-E2B (base) | OK\* | OK\* | NG | NG | OK | |
| 34 | +| Llama-2-7B | OK | OK | OK | OK | OK | |
| 35 | +| Llama-3-8B | OK\* | OK | OK | OK | OK | |
| 36 | +| Qwen3-8B | OK | OK | OK | OK | OK | |
| 37 | + |
| 38 | +### Save / Inference |
| 39 | + |
| 40 | +Each cell is `(save, transformers inference, vllm inference)`. Each |
| 41 | +entry uses OK / OK\* / NG / pending against that step's own success |
| 42 | +criterion: |
| 43 | + |
| 44 | +- **save** — save step completes and produces a saved quantized model directory. |
| 45 | +- **transformers inference** — the saved model can be loaded and run inference via HF `transformers`. |
| 46 | +- **vllm inference** — the saved model can be loaded and run inference via vLLM. |
| 47 | +- **n/a** — the recipe has no implementation for that step yet. |
| 48 | + |
| 49 | +| Model | GPTQ | QEP+GPTQ | AutoBit | AutoBit+QEP | JointQ | |
| 50 | +|---|:---:|:---:|:---:|:---:|:---:| |
| 51 | +| TinyLlama-1.1B | (OK, OK, pending) | (OK, pending, pending) | (OK, pending, pending) | (OK, pending, pending) | (n/a, n/a, n/a) | |
| 52 | +| gemma-4-E2B (base) | (OK, OK\*, pending) | (OK, pending, pending) | (OK, pending, pending) | (OK, pending, pending) | (n/a, n/a, n/a) | |
| 53 | +| Llama-2-7B | (OK, OK, pending) | (OK, pending, pending) | (OK, pending, pending) | (OK, pending, pending) | (n/a, n/a, n/a) | |
| 54 | +| Llama-3-8B | (OK, OK, pending) | (OK, pending, pending) | (OK, pending, pending) | (OK, pending, pending) | (n/a, n/a, n/a) | |
| 55 | +| Qwen3-8B | (OK, OK, pending) | (OK, pending, pending) | (OK, pending, pending) | (OK, pending, pending) | (n/a, n/a, n/a) | |
| 56 | + |
| 57 | +JointQ does not yet provide a quantized-inference layer (no |
| 58 | +`save_quantized_model` / `create_quantized_model` path), so save and |
| 59 | +inference are listed as `n/a` until those are implemented; the |
| 60 | +quantization step for JointQ is sanity-checked on the dequantized |
| 61 | +model instead. |
| 62 | + |
| 63 | +See per-recipe details in the [Results](#results) section below. |
| 64 | + |
| 65 | +## Subdirectories |
| 66 | + |
| 67 | +| Directory | Quantization recipe | Steps exercised | |
| 68 | +|---|---|---| |
| 69 | +| [`gptq/`](gptq/) | `GPTQ(wbits=4, groupsize=128)`, `qep=False` | quantize, save, load + greedy generation, PPL sanity check | |
| 70 | +| [`qep_gptq/`](qep_gptq/) | `GPTQ(wbits=4, groupsize=128)`, `qep=True` | quantize, save, PPL sanity check | |
| 71 | +| [`autobit/`](autobit/) | `AutoBitQuantizer(target_bit=4)`, candidates `GPTQ(wbits=b, groupsize=128) for b in (2,3,4,8)`, `assignment_strategy="activation_aware"`, `qep=False` | quantize, save, PPL sanity check | |
| 72 | +| [`autobit_qep/`](autobit_qep/) | `AutoBitQuantizer(target_bit=4)`, candidates `GPTQ(wbits=b, groupsize=128) for b in (2,3,4,8)`, `assignment_strategy="activation_aware"`, `qep=True` | quantize, save, PPL sanity check | |
| 73 | +| [`jointq/`](jointq/) | `JointQ(bits=4, group_size=128, symmetric=True)`, `qep=False` | quantize, PPL sanity check (on dequantized model). Save / inference: not yet implemented. | |
| 74 | + |
| 75 | +## Results |
| 76 | + |
| 77 | +### [`gptq/`](gptq/) |
| 78 | + |
| 79 | +Two phases: |
| 80 | + |
| 81 | +1. Quantize + save (`validate_gptq.py`). Calibration: `max_length=512`, |
| 82 | + `num_calibration_samples=128`. |
| 83 | +2. Load + greedy generation (`validate_load.py`). Prompt |
| 84 | + `"Fujitsu is"`, `max_new_tokens=32`. |
| 85 | + |
| 86 | +Phase 1 — quantization PPL on `wikitext-2-raw-v1`: |
| 87 | + |
| 88 | +| Model | Original PPL | Quantized PPL | Status | |
| 89 | +|---|---:|---:|---| |
| 90 | +| TinyLlama-1.1B | 7.77 | 8.69 | OK | |
| 91 | +| gemma-4-E2B (base) | 25.99 | 35.03 | OK\* | |
| 92 | +| Llama-2-7B | 5.47 | 6.59 | OK | |
| 93 | +| Llama-3-8B | 6.14 | 27.74 | OK\* | |
| 94 | +| Qwen3-8B | 9.72 | 10.72 | OK | |
| 95 | + |
| 96 | +Phase 2 — load + greedy generation: |
| 97 | + |
| 98 | +| Model | torch_dtype | Status | |
| 99 | +|---|---|---| |
| 100 | +| TinyLlama-1.1B | (default) | OK | |
| 101 | +| gemma-4-E2B | `bfloat16` | OK\* | |
| 102 | +| Llama-2-7B | (default) | OK | |
| 103 | +| Llama-3-8B | (default) | OK | |
| 104 | +| Qwen3-8B | (default) | OK | |
| 105 | + |
| 106 | +Notes: |
| 107 | + |
| 108 | +- gemma-4-E2B must be loaded as `bfloat16`; the loader's default |
| 109 | + `float16` triggers a `Half`/`BFloat16` mismatch at `lm_head`. With |
| 110 | + `bfloat16`, load + generation runs without errors but the output is |
| 111 | + degenerate (random tokens / non-Latin scripts), consistent with the |
| 112 | + warn-level PPL in phase 1. |
| 113 | +- All other models load and generate sensibly under the default dtype. |
| 114 | + |
| 115 | +See [`gptq/README.md`](gptq/README.md) for full details, generated |
| 116 | +samples, and discussion. |
| 117 | + |
| 118 | +### [`qep_gptq/`](qep_gptq/) |
| 119 | + |
| 120 | +Quantize + save (`validate_gptq.py`) with QEP on. Calibration: |
| 121 | +`max_length=1024`, `num_calibration_samples=128`. Load + inference is |
| 122 | +not exercised in this subdirectory yet. |
| 123 | + |
| 124 | +| Model | Original PPL | Quantized PPL | Status | |
| 125 | +|---|---:|---:|---| |
| 126 | +| TinyLlama-1.1B | 7.77 | 8.63 | OK | |
| 127 | +| gemma-4-E2B (base) | 25.99 | 37.82 | OK\* | |
| 128 | +| Llama-2-7B | 5.47 | 6.10 | OK | |
| 129 | +| Llama-3-8B | 6.14 | 7.14 | OK | |
| 130 | +| Qwen3-8B | 9.72 | 10.83 | OK | |
| 131 | + |
| 132 | +See [`qep_gptq/README.md`](qep_gptq/README.md) for details. |
| 133 | + |
| 134 | +### [`autobit/`](autobit/) |
| 135 | + |
| 136 | +Quantize + save (`validate_autobit.py`) with QEP off. Calibration: |
| 137 | +`max_length=512`, `num_calibration_samples=128`. Load + inference is |
| 138 | +not exercised in this subdirectory yet. |
| 139 | + |
| 140 | +| Model | Original PPL | Quantized PPL | Status | |
| 141 | +|---|---:|---:|---| |
| 142 | +| TinyLlama-1.1B | 7.77 | 8.75 | OK | |
| 143 | +| gemma-4-E2B (base) | 25.99 | 2.40e13 | NG | |
| 144 | +| Llama-2-7B | 5.47 | 5.94 | OK | |
| 145 | +| Llama-3-8B | 6.14 | 7.27 | OK | |
| 146 | +| Qwen3-8B | 9.72 | 10.74 | OK | |
| 147 | + |
| 148 | +See [`autobit/README.md`](autobit/README.md) for details. |
| 149 | + |
| 150 | +### [`autobit_qep/`](autobit_qep/) |
| 151 | + |
| 152 | +Quantize + save (`validate_autobit.py`) with QEP on. Calibration: |
| 153 | +`max_length=1024`, `num_calibration_samples=128` (reduced from defaults |
| 154 | +to keep 7-8B models within the DGX Spark 128 GB UMA budget). Load + |
| 155 | +inference is not exercised in this subdirectory yet. |
| 156 | + |
| 157 | +| Model | Original PPL | Quantized PPL | Status | |
| 158 | +|---|---:|---:|---| |
| 159 | +| TinyLlama-1.1B | 7.77 | 8.67 | OK | |
| 160 | +| gemma-4-E2B (base) | 25.99 | 1.64e14 | NG | |
| 161 | +| Llama-2-7B | 5.47 | 5.90 | OK | |
| 162 | +| Llama-3-8B | 6.14 | 7.24 | OK | |
| 163 | +| Qwen3-8B | 9.72 | 10.82 | OK | |
| 164 | + |
| 165 | +See [`autobit_qep/README.md`](autobit_qep/README.md) for details and |
| 166 | +discussion. |
| 167 | + |
| 168 | +### [`jointq/`](jointq/) |
| 169 | + |
| 170 | +Quantize only (`validate_jointq.py`) with `qep=False`. Calibration: |
| 171 | +`max_length=512`, `num_calibration_samples=128`. Save and inference |
| 172 | +are **not yet implemented** for JointQ (no `save_quantized_model` / |
| 173 | +`create_quantized_model` path), so quality is sanity-checked on the |
| 174 | +dequantized model. |
| 175 | + |
| 176 | +| Model | Original PPL | Dequantized PPL | Status | |
| 177 | +|---|---:|---:|---| |
| 178 | +| TinyLlama-1.1B | 7.77 | 8.25 | OK | |
| 179 | +| gemma-4-E2B (base) | 25.99 | 27.88 | OK | |
| 180 | +| Llama-2-7B | 5.47 | 5.64 | OK | |
| 181 | +| Llama-3-8B | 6.14 | 6.67 | OK | |
| 182 | +| Qwen3-8B | 9.72 | 10.21 | OK | |
| 183 | + |
| 184 | +See [`jointq/README.md`](jointq/README.md) for details. |
| 185 | + |
| 186 | +## Summary |
| 187 | + |
| 188 | +End-to-end execution succeeded on every model attempted under all |
| 189 | +five recipes (`gptq/`, `qep_gptq/`, `autobit/`, `autobit_qep/`, |
| 190 | +`jointq/`); no crashes or runtime failures observed. In `gptq/`, save |
| 191 | ++ load + greedy generation also ran cleanly on every model. For |
| 192 | +`jointq/`, save and inference are not yet implemented, so the |
| 193 | +quantization step is sanity-checked on the dequantized model. |
| 194 | + |
| 195 | +**Caveat on cross-recipe PPL comparison.** All five recipes use a |
| 196 | +compact calibration (`num_calibration_samples=128` and `max_length` |
| 197 | +512–1024) that sits well below typical research settings, partly |
| 198 | +because the calibration size has to fit the DGX Spark 128 GB UMA |
| 199 | +budget for 7–8B models with QEP on. PPL differences between recipes |
| 200 | +under this calibration are not large or stable enough to interpret as |
| 201 | +which recipe is "better", or to attribute recovery / regression to a |
| 202 | +specific mechanism (QEP vs AutoBit vs JointQ, etc.). PPL is reported |
| 203 | +here only to confirm that each recipe produces a model that is not |
| 204 | +obviously broken on a per-recipe basis. The bullets below describe |
| 205 | +per-recipe outcomes only; cross-recipe ordering should not be read |
| 206 | +into them. |
| 207 | + |
| 208 | +Per-recipe sanity-check observations (not accuracy claims): |
| 209 | + |
| 210 | +- TinyLlama-1.1B passes the PPL sanity check under every recipe |
| 211 | + attempted; under `gptq/`, load + greedy generation produces |
| 212 | + sensible text. |
| 213 | +- gemma-4-E2B (base) is borderline under both GPTQ-only recipes |
| 214 | + (`gptq/` 35.03, `qep_gptq/` 37.82 vs original 25.99; both OK\*). |
| 215 | + Under `gptq/`, the saved model must be loaded as `bfloat16` (the |
| 216 | + default `float16` triggers a `Half`/`BFloat16` mismatch at |
| 217 | + `lm_head`) and greedy generation produces degenerate output |
| 218 | + (random tokens / non-Latin scripts), consistent with the |
| 219 | + warn-level PPL. Under both AutoBit recipes the PPL diverges to |
| 220 | + ~10^13 (`autobit/`) and ~10^14 (`autobit_qep/`); under |
| 221 | + `autobit_qep/` the bit assignment polarized into 8-bit / 2-bit |
| 222 | + halves (observed directly in the run log). The order-of-magnitude |
| 223 | + divergence and the polarized bit assignment are not artifacts of |
| 224 | + the limited calibration: under `autobit_qep/` the same bimodal |
| 225 | + assignment was reproduced when calibration was reduced from |
| 226 | + `max_length=2048, num_calibration_samples=512` to the current |
| 227 | + `max_length=1024, num_calibration_samples=128`. This model is |
| 228 | + therefore NG under AutoBit on this hardware, regardless of QEP. |
| 229 | + Under `jointq/` it passes the PPL sanity check (27.88 vs 25.99, |
| 230 | + OK). |
| 231 | +- Llama-2-7B passes the PPL sanity check under every recipe; under |
| 232 | + `gptq/`, load + greedy generation produces sensible text. |
| 233 | +- Llama-3-8B is weak under `gptq/` (PPL 27.74 vs original 6.14, OK\*) |
| 234 | + with the compact calibration (`max_length=512`, |
| 235 | + `num_calibration_samples=128`); within range under each of the |
| 236 | + other four recipes (`qep_gptq/` 7.14, `autobit/` 7.27, |
| 237 | + `autobit_qep/` 7.24, `jointq/` 6.67). Load + greedy generation |
| 238 | + under `gptq/` runs without errors and produces sensible text. |
| 239 | +- Qwen3-8B passes the PPL sanity check under every recipe; under |
| 240 | + `gptq/`, load + greedy generation produces sensible text. |
| 241 | +- Memory: `qep_gptq/` and `autobit_qep/` at the reduced calibration |
| 242 | + (`max_length=1024`, `num_calibration_samples=128`) fit within the |
| 243 | + DGX Spark 128 GB UMA budget for all 5 models (no OOM at |
| 244 | + `mlp.down_proj` for 7–8B); larger calibration will not fit on this |
| 245 | + hardware. The QEP-off recipes (`gptq/`, `autobit/`, `jointq/`) at |
| 246 | + `max_length=512` fit comfortably within the same budget. |
| 247 | +- Save / inference: load + inference for the three QEP/AutoBit |
| 248 | + recipes is pending. For `jointq/`, save and inference are not yet |
| 249 | + implemented in OneComp; quality there is reported on the |
| 250 | + dequantized model only. |
0 commit comments