Skip to content

Commit cfa5270

Browse files
TST check that we support multioutput custom scorer in RidgeCV (scikit-learn#29884)
Co-authored-by: Adrin Jalali <adrin.jalali@gmail.com>
1 parent 938bce5 commit cfa5270

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

doc/whats_new/v1.6.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,11 @@ Changelog
257257
for the calculation of test scores.
258258
:pr:`29419` by :user:`Shruti Nath <snath-xoc>`.
259259

260+
- |Fix| :class:`linear_model.RidgeCV` now properly supports custom multioutput scorers
261+
by letting the scorer manage the multioutput averaging. Previously, the predictions
262+
and true targets were both squeezed to a 1D array before computing the error.
263+
:pr:`29884` by :user:`Guillaume Lemaitre <glemaitre>`.
264+
260265
- |Fix| :class:`linear_model.RidgeCV` now properly uses predictions on the same scale as
261266
the target seen during `fit`. These predictions are stored in `cv_results_` when
262267
`scoring != None`. Previously, the predictions were rescaled by the square root of the

sklearn/linear_model/tests/test_ridge.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2326,6 +2326,36 @@ def test_ridge_cv_multioutput_sample_weight(global_random_seed):
23262326
assert_allclose(ridge_cv.best_score_, -mean_squared_error(y, y_pred_loo))
23272327

23282328

2329+
def test_ridge_cv_custom_multioutput_scorer():
2330+
"""Check that `RidgeCV` works properly with a custom multioutput scorer."""
2331+
X, y = make_regression(n_targets=2, random_state=0)
2332+
2333+
def custom_error(y_true, y_pred):
2334+
errors = (y_true - y_pred) ** 2
2335+
mean_errors = np.mean(errors, axis=0)
2336+
if mean_errors.ndim == 1:
2337+
# case of multioutput
2338+
return -np.average(mean_errors, weights=[2, 1])
2339+
# single output - this part of the code should not be reached in the case of
2340+
# multioutput scoring
2341+
return -mean_errors # pragma: no cover
2342+
2343+
def custom_multioutput_scorer(estimator, X, y):
2344+
"""Multioutput score that give twice more importance to the second target."""
2345+
return -custom_error(y, estimator.predict(X))
2346+
2347+
ridge_cv = RidgeCV(scoring=custom_multioutput_scorer)
2348+
ridge_cv.fit(X, y)
2349+
2350+
cv = LeaveOneOut()
2351+
ridge = Ridge(alpha=ridge_cv.alpha_)
2352+
y_pred_loo = np.squeeze(
2353+
[ridge.fit(X[train], y[train]).predict(X[test]) for train, test in cv.split(X)]
2354+
)
2355+
2356+
assert_allclose(ridge_cv.best_score_, -custom_error(y, y_pred_loo))
2357+
2358+
23292359
# Metadata Routing Tests
23302360
# ======================
23312361

0 commit comments

Comments
 (0)