fix(eora): clamp covariance eigenvalues before inversion to avoid outlier adapters - #3014
Merged
Conversation
…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
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Contributor
|
Added the original EoRA calibration-data balance note to
Branch |
Collaborator
Author
|
I will merge this first to gpt-qmodel. If issues arise, we can fix in another pr. |
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.
@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_loraeigendecomposes the activation covariance matrix and forms a pseudoinverse via1 / 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 computed1/sqrt(lambda)for every mode. Whenlambdais near zero this creates arbitrarily large inverse values that propagate asNaN/Infoutliers in the low-rankA/Btensors and, in the worst case, the branchtorch.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_epsby setting theirsqrt/rsqrtcontributions 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: Ineora_compute_lora, replace theminimum-replacement logic with a relative tolerance cutoff and zero-pad the discarded spectrum beforesqrt/rsqrt. Also raiseFloatingPointErrorif 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
Result:
5 passed in 2.55sReview Requirements
Notes
This fix keeps the existing
eora_compute_lorasignature 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.