Repository navigation
Conversation
The per-group GPTQ correction reused the single global inverse Hessian for every 128-column block. OBS requires the inverse of the *remaining* columns, which changes after each block is quantized. The upper Cholesky factor U of H^-1 has the property that U[rest, rest] is the factor of the correctly updated inverse at every step, so the block update becomes solve_triangular(U[B,B], U[B,rest]) with no refactorisation. Also computes the inverse and factorisation in float64 so ill-conditioned Hessians do not silently disable GPTQ. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8jVC79MsJ4PX472pAZ1Qk Signed-off-by: rachitj27 <rjrachit06@gmail.com>
np.linalg.cholesky on a NaN/inf inverse can return a NaN factor without raising, which would have enabled GPTQ with garbage corrections. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8jVC79MsJ4PX472pAZ1Qk Signed-off-by: rachitj27 <rjrachit06@gmail.com>
…ssians - block update matches an explicit per-step recompute of the remaining column inverse (the Schur-complement reference) - GPTQ lowers calibrated output error vs plain Hadamard CQ4 - negative-definite and NaN Hessians disable GPTQ cleanly Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8jVC79MsJ4PX472pAZ1Qk Signed-off-by: rachitj27 <rjrachit06@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8jVC79MsJ4PX472pAZ1Qk Signed-off-by: rachitj27 <rjrachit06@gmail.com>
rachitj27
marked this pull request as ready for review
September 3, 2026 20:17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
quantize_hadamard, instead of reusing one global inverse for every 128-column blockRoot cause
_gptq_correct_groupslicedH^-1[B, B]andH^-1[B, rest]from a single inverse computed once per tensor. The OBS/GPTQ block update needs the inverse Hessian of the columns that are not yet quantized, which changes after every block (it becomes the Schur complement). Using the stale global inverse is only correct for the first block; every later block applies a miscalibrated correction to the remaining columns.The standard GPTQ remedy is to factor
H^-1 = U^T UwithUupper triangular. Processing columns left to right,U[rest, rest]is exactly the factor of the correctly updated inverse at every step, so the block update becomessolve_triangular(U[B, B], U[B, rest])with no refactorisation.Impact
Conversion only. The weight file format, engine, and inference speed are unchanged; the stored indices and norms are closer to the original weights on calibration data.
Measured with hook-collected Hessians and diagonal-derived input scales (
collect_text_hessiansand_input_scale_from_diag) on a 1024→2048→1024 MLP block, evaluating output error on held-out activations. Values are error relative to plain Hadamard CQ with no GPTQ, lower is better.The old correction plateaus at roughly 35–40% error reduction regardless of width, while the fixed version keeps improving as layers get wider.
Related: #767 and #790 cover calibration being silently skipped. This change only matters when GPTQ actually runs, so those fixes and this one compound.
Validation
python -m pytest cactus/convert/tests -q(83 passed)cactus/convert/tests/test_cq.py:test_gptq_cholesky_block_update_matches_explicit_obs: block update matches a reference that recomputesinv(H[start:, start:])from scratch at every grouptest_gptq_reduces_calibrated_error: GPTQ strictly lowers calibrated output error vs plain Hadamard CQ4test_gptq_disabled_on_bad_hessian/test_gptq_disabled_on_nan_hessian: negative-definite and NaN Hessians fall back withgptq_used=Falseand indices identical to the no-GPTQ baselinegit diff --checkclean🤖 Generated with Claude Code