Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dbed806

Browse filesBrowse files
authored
FIX Fixes regression in CCA due to change of cutoff values in SciPy (#19646)
1 parent a67b284 commit dbed806
Copy full SHA for dbed806

File tree

Expand file treeCollapse file tree

3 files changed

+41
-2
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+41
-2
lines changed

‎doc/whats_new/v0.24.rst

Copy file name to clipboardExpand all lines: doc/whats_new/v0.24.rst
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ Changelog
1919
:term:`get_feature_names` on transformers with an empty column selection.
2020
:pr:`19579` by `Thomas Fan`_.
2121

22+
:mod:`sklearn.cross_decomposition`
23+
..................................
24+
25+
- |Fix| Fixed a regression in :class:`cross_decomposition.CCA`. :pr:`19646`
26+
by `Thomas Fan`_.
27+
2228
:mod:`sklearn.ensemble`
2329
.......................
2430

‎sklearn/cross_decomposition/_pls.py

Copy file name to clipboardExpand all lines: sklearn/cross_decomposition/_pls.py
+19-2Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,24 @@
2323
__all__ = ['PLSCanonical', 'PLSRegression', 'PLSSVD']
2424

2525

26+
def _pinv2_old(a):
27+
# Used previous scipy pinv2 that was updated in:
28+
# https://github.com/scipy/scipy/pull/10067
29+
# We can not set `cond` or `rcond` for pinv2 in scipy >= 1.3 to keep the
30+
# same behavior of pinv2 for scipy < 1.3, because the condition used to
31+
# determine the rank is dependent on the output of svd.
32+
u, s, vh = svd(a, full_matrices=False, check_finite=False)
33+
34+
t = u.dtype.char.lower()
35+
factor = {'f': 1E3, 'd': 1E6}
36+
cond = np.max(s) * factor[t] * np.finfo(t).eps
37+
rank = np.sum(s > cond)
38+
39+
u = u[:, :rank]
40+
u /= s[:rank]
41+
return np.transpose(np.conjugate(np.dot(u, vh[:rank])))
42+
43+
2644
def _get_first_singular_vectors_power_method(X, Y, mode="A", max_iter=500,
2745
tol=1e-06, norm_y_weights=False):
2846
"""Return the first left and right singular vectors of X'Y.
@@ -44,8 +62,7 @@ def _get_first_singular_vectors_power_method(X, Y, mode="A", max_iter=500,
4462
# As a result, and as detailed in the Wegelin's review, CCA (i.e. mode
4563
# B) will be unstable if n_features > n_samples or n_targets >
4664
# n_samples
47-
X_pinv = pinv2(X, check_finite=False, cond=10*eps)
48-
Y_pinv = pinv2(Y, check_finite=False, cond=10*eps)
65+
X_pinv, Y_pinv = _pinv2_old(X), _pinv2_old(Y)
4966

5067
for i in range(max_iter):
5168
if mode == "B":

‎sklearn/cross_decomposition/tests/test_pls.py

Copy file name to clipboardExpand all lines: sklearn/cross_decomposition/tests/test_pls.py
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,3 +552,19 @@ def test_svd_flip_1d():
552552

553553
assert_allclose(v, v_expected.ravel())
554554
assert_allclose(v, [-1, -2, -3])
555+
556+
557+
def test_loadings_converges():
558+
"""Test that CCA converges. Non-regression test for #19549."""
559+
X, y = make_regression(n_samples=200, n_features=20, n_targets=20,
560+
random_state=20)
561+
562+
cca = CCA(n_components=10, max_iter=500)
563+
564+
with pytest.warns(None) as record:
565+
cca.fit(X, y)
566+
# ConvergenceWarning is not raised
567+
assert not record
568+
569+
# Loadings converges to reasonable values
570+
assert np.all(np.abs(cca.x_loadings_) < 1)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.