Skip to content

fix(eora): clamp covariance eigenvalues before inversion to avoid outlier adapters - #3014

Merged
Qubitium merged 2 commits into
mainfrom
fix-eora-clamp
Aug 15, 2026
Merged

fix(eora): clamp covariance eigenvalues before inversion to avoid outlier adapters#3014
Qubitium merged 2 commits into
mainfrom
fix-eora-clamp

Conversation

@Qubitium

@Qubitium Qubitium commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

@nbasyl @hutm @cmhungsteve Please review. The following bug was encountered by me doing testing on EoRA. The lower the bpw, the higher the chance this becomes and the more damage it will cause. Most of the time it just manifest it self silently as lower EoRA recovery scores and was very sneaky to catch. It often does not manifest as catastrophic failure which is the sneaky part.

Summary

eora_compute_lora eigendecomposes the activation covariance matrix and forms a pseudoinverse via 1 / sqrt(eigenvalue). Numerical noise in the float32 accumulated covariance can yield tiny or slightly negative eigenvalues; the old code replaced negatives with the smallest positive eigenvalue, then computed 1/sqrt(lambda) for every mode. When lambda is near zero this creates arbitrarily large inverse values that propagate as NaN/Inf outliers in the low-rank A/B tensors and, in the worst case, the branch torch.min(L[L > 0]) crashes when every eigenvalue is non-positive.

Clamp the spectrum to a numerical-rank tolerance: discard eigenvalues at or below max(lambda) * max(1, n) * float32_eps by setting their sqrt/rsqrt contributions to zero, so they do not participate in the pseudoinverse. This produces finite adapters for rank-deficient or numerically indefinite covariances.

What Changed

  • gptqmodel/eora/eora.py: In eora_compute_lora, replace the minimum-replacement logic with a relative tolerance cutoff and zero-pad the discarded spectrum before sqrt/rsqrt. Also raise FloatingPointError if the eigensolve returns non-finite eigenvalues.
  • tests/test_eora.py: New focused unit tests for covariance spectra containing negative/tiny eigenvalues and the all-negative pathological case.

Tests

  • I added a new simple/fast unit test for this change.
  • I ran the new targeted test locally before opening this PR.
cd tests && python -m pytest test_eora.py -x -q

Result: 5 passed in 2.55s

Review Requirements

  • Every changed file has been reviewed by a human.
  • I checked that the code matches existing project structure, APIs, and conventions.
  • I avoided unnecessary monkeypatching and used the project's normal extension points where possible.

Notes

This fix keeps the existing eora_compute_lora signature and does not change the public EoRA API. The cutoff follows the same float32 numerical-rank reasoning used in the codebase's other Hessian/covariance paths.

…lier adapters

EoRA builds a low-rank adapter from the quantized-weight residual and the
covariance of activations. The covariance is accumulated in float32 and then
eigendecomposed in float64; numerical noise can produce tiny or slightly
negative eigenvalues. The previous code replaced negative eigenvalues with the
smallest positive one and then computed 1/sqrt(lambda) for every mode, which
creates arbitrarily large inverse values and propagates them as NaN/Inf outliers
in the float16/float32 LoRA tensors.

Truncate the spectrum at a numerical-rank tolerance derived from float32
epsilon instead: eigenvalues at or below max(lambda) * max(1, n) * eps are
set to zero so they do not participate in the pseudoinverse. This makes the
adapter finite even when the covariance is rank-deficient or numerically
indefinite.

Fixes the crash when every eigenvalue is non-positive (L[L > 0] is empty) and
guards against tiny outlier eigenvalues that blow up 1/sqrt(lambda).

- Add tests/test_eora.py with deterministic negative and all-negative eigenvalue cases
@Qubitium Qubitium self-assigned this Aug 13, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Added the original EoRA calibration-data balance note to eora_compute_lora as a docstring:

When expanding the calibration data size for EoRA, I suggest maintaining the balance by allocating 50% to general input (C4) and the remaining 50% to downstream task data.

Branch fix-eora-clamp updated and tests still pass (pytest tests/test_eora.py -q → 5 passed).

@Qubitium

Copy link
Copy Markdown
Collaborator Author

I will merge this first to gpt-qmodel. If issues arise, we can fix in another pr.

@Qubitium
Qubitium merged commit 7df3d1e into main Aug 15, 2026
6 checks passed
@Qubitium
Qubitium deleted the fix-eora-clamp branch August 15, 2026 07:19
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