Skip to content

TST: xfail part of test_partial_fit() on Linux - #138

Open
tylerjereddy wants to merge 2 commits into
lanl:mainfrom
tylerjereddy:treddy_issue_117_xfail
Open

tylerjereddy wants to merge 2 commits into
lanl:mainfrom
tylerjereddy:treddy_issue_117_xfail

Conversation

@tylerjereddy

@tylerjereddy tylerjereddy commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator
  • Related to TST, CI: test_partial_fit is failing in Linux CI (with NumPy 2.5.0) #117. That issue has been causing our CI to fail for almost 4 months now. While I was hoping someone would fix the matter properly, we can't continue to have CI failing all the time because we need to be able to assess the quality of other thrusts of work.

  • So, this branch proposes to xfail a subset of test_partial_fit() on Linux to avoid the failure. The issue will remain open--this is just to allow us to assess the correctness of incoming changes without interference from TST, CI: test_partial_fit is failing in Linux CI (with NumPy 2.5.0) #117.

  • I confirmed that this allows the full testsuite to pass on an x86_64 Linux machine with NumPy 2.5.4 installed from PyPI.


AI usage disclosure: Claude Opus 5.5 was used to extend the xfail to include the Windows platform after I manually handled the Linux part (accessing a windows machine is possible, but a bit annoying for me)

* Related to lanlgh-117. That issue has been causing our CI to
fail for almost 4 months now. While I was hoping someone
would fix the matter properly, we can't continue to have CI
failing all the time because we need to be able to assess the
quality of other thrusts of work.

* So, this branch proposes to `xfail` a subset of `test_partial_fit()`
on Linux to avoid the failure. The issue will remain open--this
is just to allow us to assess the correctness of incoming changes
without interference from lanlgh-117.

* I confirmed that this allows the full testsuite to pass on an
x86_64 Linux machine with NumPy `2.5.4` installed from PyPI.
Comment thread src/gfdl/tests/test_model.py Outdated
(GFDLClassifier, False, "coeff_"),
(EnsembleGFDLClassifier, None, "coeffs_"),
pytest.param(EnsembleGFDLClassifier, None, "coeffs_",
marks=pytest.mark.xfail(condition="sys.platform == 'linux'",

@tylerjereddy tylerjereddy Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this is a bit more aggressive than strictly needed since I believe the issue only affects x86_64 Linux, and even then, only for a subset of the EnsembleGFDLClassifier cases/scenarios.

Still, this is reasonably simple, and shimming around only the single exact failure case would be a fair bit messier.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI is failing because the shim is also needed on Windows and because of connectivity issues similar to those reported in gh-98. I can push in a shim to help with the former, but the latter issue has been open for months without help and will need to be fixed separately.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I've pushed in a commit to xfail test_partial_fit() similarly on windows for the ensembling flavor of the estimator. I used Opus 5.5 to add the Windows shim, since I can't test as easily on that platform, so I'll update my AI disclosure above shortly.

I did confirm manually that we still pass tests on Linux in the scenario above after that update.

sdtemple added a commit to sdtemple/GFDL that referenced this pull request Oct 21, 2026
* `xp.linalg.solve` documation for `partial_fit`
	in non-ensemble GFDL estimators

* `softmax` from @activations.py achieves the same
	thing as in `partial_fit` custom written
	with `scipy.special.logsumexp`

* These would eventually need to be addressed
	in an ensemble branch in the same way

* Reverted to `rtol=1e-3` for `test_partial_fit`
	which had `pinv` instability in `EnsembleGFDLClassifier`.
	It looks like Tyler will `xfail` this case in lanl#138
* Adjust test_partial_fit() to also `xfail` on the
Windows platform, because it is also affected by
lanlgh-117.
sdtemple added a commit to sdtemple/GFDL that referenced this pull request Oct 23, 2026
* `xp.linalg.solve` documation for `partial_fit`
	in non-ensemble GFDL estimators

* `softmax` from @activations.py achieves the same
	thing as in `partial_fit` custom written
	with `scipy.special.logsumexp`

* These would eventually need to be addressed
	in an ensemble branch in the same way

* Reverted to `rtol=1e-3` for `test_partial_fit`
	which had `pinv` instability in `EnsembleGFDLClassifier`.
	It looks like Tyler will `xfail` this case in lanl#138
@nray

nray commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

@tylerjereddy : You already suggested a solution here and adopting that change makes all the partial fit tests pass for me on Chicoma (tried numpy versions 2.3.0, 2.4.0, 2.5.0-4). That chain of conversations seemed to agree that this would make our partial fit estimators robust. What is the blocker for adopting the solution you found ?

sdtemple added a commit to sdtemple/GFDL that referenced this pull request Oct 24, 2026
* `xp.linalg.solve` documation for `partial_fit`
	in non-ensemble GFDL estimators

* `softmax` from @activations.py achieves the same
	thing as in `partial_fit` custom written
	with `scipy.special.logsumexp`

* These would eventually need to be addressed
	in an ensemble branch in the same way

* Reverted to `rtol=1e-3` for `test_partial_fit`
	which had `pinv` instability in `EnsembleGFDLClassifier`.
	It looks like Tyler will `xfail` this case in lanl#138
@tylerjereddy

Copy link
Copy Markdown
Collaborator Author

What is the blocker for adopting the solution you found ?

@nray because the NumPy pinv with Hermitian assumption didn't work as the discussion in gh-120 explains--some of the NumPy 2.5.x series releases had problems with some other tests in our suite when we did that. Other tests will start failing if you switch to the Hermitian assumption across newer NumPy versions, and switching to the SciPy version of the Hermitian calculation is just delaying the inevitable introduction of the newer linalg backend on the next PyPI release of SciPy.

The numerical stability of the partial_fit() algorithm, exacerbated by the batching on already-problematic numerical inputs, combined with the stringency of our current partial_fit() testing, backs us into a tough spot here, and some linalg experts have already weighed in on the issue. We likely need algorithmic improvements, some of which are discussed there, but our testing is also probably causing unrealistic expectations.

Do I currently trust that someone on the team can clean up the algorithms and testing confidently and cleanly? I'm not so sure, maybe, but not without a very large time investment and a likely difficult debate about how much we can relax our tests to make them more realistic. I'd welcome an attempt, and as I've noted in the issue, LLMs have interesting ideas, but at the cost of other current priorities? Seems like it could be a big timesink, and I've already invested a fair bit of time pushing on it. So, that's the main argument to punt for now.

@sdtemple

Copy link
Copy Markdown
Collaborator

You already suggested a solution here and adopting that change makes all the partial fit tests pass for me on Chicoma (tried numpy versions 2.3.0, 2.4.0, 2.5.0-4). That chain of conversations seemed to agree that this would make our partial fit estimators robust.

@nray That shim uses the keyword argument hermitian. If we were to adopt array API standard language, xp.linalg.pinv does not support the keyword argument hermitian.

https://data-apis.org/array-api/2025.12/extensions/generated/array_api.linalg.pinv.html#array_api.linalg.pinv

@sdtemple

Copy link
Copy Markdown
Collaborator

The numerical stability of the partial_fit() algorithm, exacerbated by the batching on already-problematic numerical inputs, combined with the stringency of our current partial_fit() testing, backs us into a tough spot here, and some linalg experts have already weighed in on the issue.

@eiviani-lanl and I have also identified challenges with rtol and atol stringencies for partial_fit when you try to match all fitted coefficients between NumPy versus other backends.

our testing is also probably causing unrealistic expectations

That may be the case. For tests that perform many combinations of all the RVFL argument values (1000s), we often/always end up with a few problematic inputs.

@sdtemple

Copy link
Copy Markdown
Collaborator

our testing is also probably causing unrealistic expectations

To be fair, I wouldn't mind relaxing the tols a bit more, but we're already at rtol=1e-05, atol=0.001. If there's some other allowable tolerance measure, for example if it is acceptable for a single element in the arrays to deviate by a lot more than that, I'd be open to that, but I haven't seen that clearly expressed. For example, the two problem tests only have mismatches at 1/100 and 1/70 elements. I don't think I know enough about the math to say that we should just allow a single element to deviate by a larger threshold.

One solution could be distinguish between which types of arrays we could allow to have a small proportion of mismatches. For instance, I would argue that the predicted values ought to be very (or uniformly) close, whereas matching all fitted coefficients could be unrealistic. IIRC, the linear algebra experts in the OpenBLAS discussions mentioned that matching all coefficients would be challenging.

to have a small proportion of mismatches

This is less brittle when increasing model sizes versus 1 single mismatch out of say 10000.

@sdtemple

Copy link
Copy Markdown
Collaborator

I scanned with grep through all the scikit-learn estimators that I could find which have a partial_fit method.

For estimators where I found a model attribute being assert_allclose'd they were tested once with 1 small dataset (like 6 data points). E.g., GaussianNB tests the variance of 2 label groups fitted to 6 data points.

For estimators like MLPRegressor and MLPClassifier, they only test assert_allclose for predicted values in 1 small dataset.

For decompositions (IncrementalPCA) or scalers (MinMaxScaler), they may test attributes' closeness like components_ but only in 1 small dataset.

Overall, I don't see evidence of scikit-learn partial_fit running assert_allclose for as many permutations or as large of datasets as we do, and they rarely check array attribute values, especially not coefficients.

@sdtemple

Copy link
Copy Markdown
Collaborator

One solution could be distinguish between which types of arrays we could allow to have a small proportion of mismatches. For instance, I would argue that the predicted values ought to be very (or uniformly) close, whereas matching all fitted coefficients could be unrealistic.

This above was a bad suggestion by me. I don't think that'll remedy the situation, at least not for Array API tests with float32. It may work for the ensemble estimator with float64.

@tylerjereddy

Copy link
Copy Markdown
Collaborator Author

Just noting that I talked to @sdtemple and @nray separately in person this morning. There seemed to be some general agreement that we might relax some of our partial_fit() testing as long as it is justified by how sklearn currently tests partial_fit(), and this may in turn propagate some benefits to blockers on the array API testing thrust as well.

I believe @nray had a frontier model check sklearn for how they do this, and Seth did some grepping above. I also did some grepping a few weeks ago in the discussion starting at #117 (comment).

I suggest carrying the discussion/analysis forward in that issue and coordinating there, and once a clear path of action is decided there you can just supersede my two PRs related to this matter if a new PR doing the "right thing" is opened. I don't think this has to be too complicated, just justify our level of stringency/checking based on how sklearn does it--avoid deleting entire tests, and instead probably just relax them based on what sklearn does.

sdtemple added a commit to sdtemple/GFDL that referenced this pull request Oct 26, 2026
* `xp.linalg.solve` documation for `partial_fit`
	in non-ensemble GFDL estimators

* `softmax` from @activations.py achieves the same
	thing as in `partial_fit` custom written
	with `scipy.special.logsumexp`

* These would eventually need to be addressed
	in an ensemble branch in the same way

* Reverted to `rtol=1e-3` for `test_partial_fit`
	which had `pinv` instability in `EnsembleGFDLClassifier`.
	It looks like Tyler will `xfail` this case in lanl#138
sdtemple added a commit to sdtemple/GFDL that referenced this pull request Oct 26, 2026
* `xp.linalg.solve` documation for `partial_fit`
	in non-ensemble GFDL estimators

* `softmax` from @activations.py achieves the same
	thing as in `partial_fit` custom written
	with `scipy.special.logsumexp`

* These would eventually need to be addressed
	in an ensemble branch in the same way

* Reverted to `rtol=1e-3` for `test_partial_fit`
	which had `pinv` instability in `EnsembleGFDLClassifier`.
	It looks like Tyler will `xfail` this case in lanl#138
sdtemple added a commit to sdtemple/GFDL that referenced this pull request Oct 26, 2026
* `xp.linalg.solve` documation for `partial_fit`
	in non-ensemble GFDL estimators

* `softmax` from @activations.py achieves the same
	thing as in `partial_fit` custom written
	with `scipy.special.logsumexp`

* These would eventually need to be addressed
	in an ensemble branch in the same way

* Reverted to `rtol=1e-3` for `test_partial_fit`
	which had `pinv` instability in `EnsembleGFDLClassifier`.
	It looks like Tyler will `xfail` this case in lanl#138

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants