Skip to content

Commit b9ccf05

Browse files
committed
Fixing PCovR to not mess with data shape
1 parent f2d212c commit b9ccf05

File tree

5 files changed

+20
-18
lines changed

5 files changed

+20
-18
lines changed

examples/pcovr/PCovR_Regressors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
X_scaled = X_scaler.fit_transform(X)
3030

3131
y_scaler = StandardScaler()
32-
y_scaled = y_scaler.fit_transform(y.reshape(-1, 1)).ravel()
32+
y_scaled = y_scaler.fit_transform(y.reshape(-1, 1))
3333

3434

3535
# %%

examples/pcovr/PCovR_Scaling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757

5858
pcovr_scaled = PCovR(mixing=0.5, n_components=4).fit(X_scaled, y_scaled)
5959
T_scaled = pcovr_scaled.transform(X_scaled)
60-
Yp_scaled = y_scaler.inverse_transform(pcovr_scaled.predict(X_scaled).reshape(-1, 1))
60+
Yp_scaled = y_scaler.inverse_transform(pcovr_scaled.predict(X_scaled))
6161

6262
fig, ((ax1_T, ax2_T), (ax1_Y, ax2_Y)) = plt.subplots(2, 2, figsize=(8, 10))
6363

src/skmatter/decomposition/_pcovr.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ def fit(self, X, Y, W=None):
310310
self._fit_sample_space(X, Y.reshape(Yhat.shape), Yhat, W)
311311

312312
self.pxy_ = self.pxt_ @ self.pty_
313-
if len(Y.shape) == 1 or Y.shape[1] == 1:
313+
if len(Y.shape) == 1:
314314
self.pxy_ = self.pxy_.reshape(
315315
X.shape[1],
316316
)
@@ -637,10 +637,6 @@ def score(self, X, y, T=None):
637637
"""
638638
X, y = validate_data(self, X, y, reset=False)
639639

640-
if y.ndim == 2:
641-
if y.shape[1] == 1:
642-
y = y.ravel()
643-
644640
if T is None:
645641
T = self.transform(X)
646642

src/skmatter/utils/_pcovr_utils.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,18 @@ def check_lr_fit(regressor, X, y):
4141
# Check compatibility with X
4242
validate_data(fitted_regressor, X, y, reset=False, multi_output=True)
4343

44-
if y.ndim == 2:
45-
if y.shape[1] == 1:
46-
y = y.ravel()
47-
4844
# Check compatibility with y
45+
46+
# TO DO: This if statement is a band-aid for the case when we pass in a
47+
# prefitted Ridge() or RidgeCV(), which, as of sklearn 1.6, will create
48+
# coef_ with shape (n_features, ) even if fitted on a 2-D y with one target.
49+
# In the future, we can optimize this block if LinearRegression() also changes.
50+
4951
if fitted_regressor.coef_.ndim != y.ndim:
52+
if y.ndim == 2:
53+
if fitted_regressor.coef_.ndim == 1 and y.shape[1] == 1:
54+
return fitted_regressor
55+
5056
raise ValueError(
5157
"The regressor coefficients have a dimension incompatible with the "
5258
"supplied target space. The coefficients have dimension "

tests/test_pcovr.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,14 @@ def test_lr_with_t_errors(self):
111111
projection and that the prediction error increases with `mixing`.
112112
"""
113113
prev_error = -1.0
114-
Ytrue = self.Y.ravel()
115114

116115
for mixing in np.linspace(0, 1, 11):
117116
pcovr = self.model(mixing=mixing, n_components=2, tol=1e-12)
118117
pcovr.fit(self.X, self.Y)
119118

120119
T = pcovr.transform(self.X)
121120
Yp = pcovr.predict(T=T)
122-
error = np.linalg.norm(Ytrue - Yp) ** 2.0 / np.linalg.norm(Ytrue) ** 2.0
121+
error = np.linalg.norm(self.Y - Yp) ** 2.0 / np.linalg.norm(self.Y) ** 2.0
123122

124123
with self.subTest(error=error):
125124
self.assertFalse(np.isnan(error))
@@ -483,21 +482,22 @@ def test_none_regressor(self):
483482
self.assertTrue(pcovr.regressor_ is not None)
484483

485484
def test_incompatible_coef_dim(self):
486-
# self.Y is 2D with one target
485+
# self.Y is 1D with one target
487486
# Don't need to test X shape, since this should
488487
# be caught by sklearn's validate_data
488+
Y_2D = np.column_stack((self.Y, self.Y))
489489
regressor = Ridge(alpha=1e-8, fit_intercept=False, tol=1e-12)
490-
regressor.fit(self.X, self.Y)
490+
regressor.fit(self.X, Y_2D)
491491
pcovr = self.model(mixing=0.5, regressor=regressor)
492492

493493
# Dimension mismatch
494494
with self.assertRaises(ValueError) as cm:
495-
pcovr.fit(self.X, np.zeros((self.Y.shape[0], 2)))
495+
pcovr.fit(self.X, self.Y)
496496
self.assertEqual(
497497
str(cm.exception),
498498
"The regressor coefficients have a dimension incompatible with the "
499-
"supplied target space. The coefficients have dimension 1 and the targets "
500-
"have dimension 2",
499+
"supplied target space. The coefficients have dimension 2 and the targets "
500+
"have dimension 1",
501501
)
502502

503503
def test_incompatible_coef_shape(self):

0 commit comments

Comments
 (0)