-
-
Notifications
You must be signed in to change notification settings - Fork 26k
[MRG] Fix ARDRegression accuracy issue with scipy 1.3.0 (Issue #14055) #14067
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MRG] Fix ARDRegression accuracy issue with scipy 1.3.0 (Issue #14055) #14067
Conversation
701aac5
to
e54ec68
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't confirmed that this is the same logic as scipy < 1.3, but it otherwise looks good.
I think we should include this in 0.21.3 as a compatibility fix.
Please add an entry to the change log under 0.21.3 at doc/whats_new/v0.21.rst
. Like the other entries there, please reference this pull request with :pr:
and credit yourself (and other contributors if applicable) with :user:
.
But it seems the test fails on some CI:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add the what's new entry?
I makes me uncomfortable that the |
I agree that it would be good to look at how scipy substantiated their
change and why that should not apply here
|
Hey folks, yeah I was hoping that relaxing the test-condition a little bit would get a pass from the various CI-builds. Weirdly the latest CI-fail seems to be on an unrelated unit-test (RANSACRegressor?) so I'm not sure what's going on there. Certainly in agreement that a more principled fix would be desirable, and this is something of a temporary kludge. Unfortunately I think a proper rework will require a decent understanding of both the ARDRegressor and scipy pinvh, and I have neither (or the time to grok them) right now. This is something of a benchmark routine for the day job, so it's in our interests for it to work nicely but not a priority. If you still want to get this merged in I'll add the various what's new entries as requested and see if it passes on CI next time around, just haven't gotten around to it yet. |
7178528
to
ab5aa91
Compare
I've added the what's new entry, hopefully got all the formatting correct. Happily the tests seem to be passing now! |
Do we want this in 0.21.3? @NicolasHug? @ogrisel |
I'm OK with the idea. We would still need to open an issue to find out how to make it work with the new Regarding the proposed PR: we should probably port the whole |
sklearn/linear_model/bayes.py
Outdated
dtype_code = sigma_inverse_.dtype.char.lower() | ||
factor = {'f': 1E3, 'd': 1E6} | ||
pinvh_cond_factor = factor[dtype_code] * np.finfo(dtype_code).eps | ||
s, u = linalg.eigh(sigma_inverse_, lower=True, check_finite=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eigh
is going to be called again in pinvh
, we might just as well port the whole pinvh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds sensible, good way to pin behaviour across Scipy versions. Where should such 'vendored' code go in the scikit-learn codebase - 'utils.pinvh', or maybe 'utils.linalg'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's a lot of code, you can put it under sklearn/externals/_scipy_linalg.py
then import it or not depending on the scipy version from within sklearn/utils/fixes.py
.
If it's not that much code, you can put in in utils.fixes
directly.
The original issue should still be open so we can work on the underlying issue. |
d057f2a
to
942adb4
Compare
Ok, compatibility-fix copy of scipy.linalg.pinvh in place, which in hindsight makes this PR much simpler to parse. Fingers crossed on the CI not flaking out. |
942adb4
to
b7f2829
Compare
Please append commits rather than squashing and force-pushing. We will squash upon merge. |
@NicolasHug / @thomasjpfan are you happy with this? |
scikit-learn/sklearn/linear_model/bayes.py Line 554 in f4fc84a
# calcuate condition for pinvh
pinvh_cond = 1E6 * np.finfo(X.dtype).eps
# Compute sigma and mu (using Woodbury matrix identity)
def update_sigma(X, alpha_, lambda_, keep_lambda, n_samples):
sigma_ = pinvh(np.eye(n_samples) / alpha_ +
np.dot(X[:, keep_lambda] *
np.reshape(1. / lambda_[keep_lambda], [1, -1]),
X[:, keep_lambda].T), cond=pinvh_cond)
Edit: This is not the right approach. Lets merge this PR after https://github.com/scikit-learn/scikit-learn/pull/14067/files#r306688549 is resolved. |
If we want to include this in 0.21.3, it's got to be merged in the next day or two. |
Made some very minor cleaning in Thanks @timstaley! |
Reference Issues/PRs
Fixes #14055
What does this implement/fix? Explain your changes.
This simply implements the strategy for choosing a
pinvh
singular value threshold that was the default in Scipy prior 1.3.0. (The new default strategy gives a lower threshold, producing a less stable convergence of ARDRegression).Any other comments?
Unfortunately the way the
cond
parameter toscipy.linalg.pinvh
is treated has changed between 1.2 and 1.3; in 1.2 the parameter was always multiplied by the largest absolute value of the singular decomposition, whereas in 1.3 it is left as-is. This means that applying this fix in 1.2.1 results in larger threshold than before!Of course, we could pin behaviour more precisely by checking for the version of Scipy present, I'm curious to get the Sklearn regular dev-team's opinion on this.