Skip to content

feat(quantize): AdaRound INT4 learned-rounding PTQ + dimensional Quantizer spec#44

Closed
nathanhubens wants to merge 3 commits into
masterfrom
feat/quantize-adaround
Closed

feat(quantize): AdaRound INT4 learned-rounding PTQ + dimensional Quantizer spec#44
nathanhubens wants to merge 3 commits into
masterfrom
feat/quantize-adaround

Conversation

@nathanhubens

Copy link
Copy Markdown
Collaborator

The first validated safe-quant technique becomes a real fasterai feature — built into a coherent dimensional design rather than as a one-off.

AdaRound (criteria='adaround')

Learned-rounding INT4 PTQ (Nagel 2020): learns per-weight round-up/down to minimize output reconstruction, so INT4 holds accuracy where round-to-nearest collapses.

  • adaround_quantize(model, calibration_dl, w_bits=4, granularity='channel', act_bits=None, ...) — accepts a fastai DataLoaders, a torch DataLoader, or a plain list of batches.
  • Measured (ResNet-18): INT4+AdaRound recovers the RTN cliff — +26 pt at full budget → ~1 pt below INT8. Architecture-dependent: viable for redundant CNNs (ResNet-class), not efficient/depthwise nets (route those to INT8). INT4 is a size lever, not a CPU-speed one (our own benchmark: W4 is ~4× slower on CPU).
  • Fake-quant faithful for accuracy; real INT4-kernel export is the deployment follow-up.

Dimensional Quantizer spec (nbs/quantize/DIMENSIONAL_DESIGN.md)

North-star mirroring Sparsifier — every quant technique is a composable value on an axis (granularity × context × criteria × schedule × dtype), not a bespoke function. AdaRound is the first criteria; the stranded quantize_mixed work → context='mixed'; SmoothQuant → a pre-quant transform. Same mechanism/decision split as pruning (fasterai applies; fasterrecipes decides mixed-precision via sensitivity) → one allocation engine for both prune-ratio AND bit-width.

Validation

  • Fast tests green: init==RTN correctness gate, reconstruction-improves, failure modes (no-calibration → clear error, list-of-batches accepted, per-tensor + W4A8 paths).
  • #| slow test green: real +14 pt ResNet-18 Imagenette recovery (short notebook budget; full budget ≈ +26 pt).
  • Independently re-verified: gate holds, clear errors, spec-aligned granularity string API.

…tizer spec

AdaRound (Nagel 2020) — the first validated safe-quant technique. Learns per-weight
round up/down to minimize output reconstruction, so INT4 holds accuracy where
round-to-nearest collapses.

- adaround_quantize(model, calibration_dl, w_bits=4, granularity='channel', ...) —
  accepts a fastai DataLoaders, a torch DataLoader, or a list of batches.
- Measured (ResNet-18): INT4+AdaRound recovers the RTN cliff (+26pt full budget ->
  ~1pt below INT8). Architecture-dependent: viable for redundant CNNs (ResNet-class),
  NOT efficient/depthwise nets (route those to INT8). INT4 = size lever, not CPU speed.
- Tests: init==RTN correctness gate, reconstruction-improves, failure modes
  (no-calibration -> clear error, list-of-batches accepted), + a #|slow ResNet-18
  recovery integration test.
- Shaped as criteria='adaround' toward the dimensional Quantizer (DIMENSIONAL_DESIGN.md:
  granularity x context x criteria x schedule x dtype, mirroring Sparsifier).
Aligns the weight grid to the ONNX/ORT signed-INT4 convention so exported
integers land on the deployment grid, and uses all 16 INT4 values (strict
quality improvement). weight_scale now returns (scale, qmin, qmax);
rtn_quant/_hard_quant_from_V/adaround_layer clamp to [qmin, qmax]. The
init==RTN correctness gate is preserved (floor-based round-half-up so RTN
matches the hard-round on the new grid). Full nbdev-test green (fast + slow).

Lifts standard ONNX-export accuracy 71.75 -> 74.57 (ResNet-18). NOTE: grid
alignment alone is NOT lossless (ORT recalibrates scale from the quantized
weights' absmax) — the faithful QDQ-export helper (bake exact int4+scale,
verified 79.11 ~ fake-quant 78.34) is the true deployment path (follow-up).
…nt path)

AdaRound's learned rounding survives to a real INT4 ONNX ONLY if you write the
exact int4+scale yourself — standard exporters recalibrate the per-channel scale
and shed 4-7pt (measured). This closes the deployment gap:
- adaround_quantize now stashes model._adaround_qparams (exact per-layer scale +
  qmin/qmax), captured pre-quant (the scale is unrecoverable once W <- scale*int).
- adaround_to_onnx(model, sample, path): FP32 ONNX -> ORT QDQ structure ->
  overwrite the scale + int4 weight initializers with AdaRound's EXACT values ->
  a QDQ ONNX that carries the learned rounding. _pack_int4/_unpack_int4 helpers.
- Verified faithful (slow test): ResNet-18 INT4, fake-quant 66.41 -> deployed
  ONNX 67.19 (delta -0.78pt, matches the standalone -0.76); int4 ONNX 5.99MB vs
  FP32 46.75MB (7.8x); dequant weight error 1.2e-7.

Completes the loop: AdaRound accuracy -> real INT4 artifact at the SAME accuracy
-> measurable via fasterrecipes evaluate_accuracy. nbdev-test green (fast+slow).
@nathanhubens
nathanhubens deleted the feat/quantize-adaround branch July 14, 2026 08:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant