-
-
Notifications
You must be signed in to change notification settings - Fork 25.9k
FIX add metadata routing to CV splitters in RidgeCV
and RidgeClassifierCV
#29634
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
Changes from all commits
e3d4c1a
3956f2c
bc4804e
8125194
2c2db3d
336057a
feca19f
1b67c17
250b977
142e23c
72f4286
d5d3a1c
06cddaa
3ad1190
8ee822d
6c73dd2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2178,8 +2178,6 @@ def fit(self, X, y, sample_weight=None, score_params=None): | |
|
||
X_mean, *decomposition = decompose(X, y, sqrt_sw) | ||
|
||
scorer = self._get_scorer() | ||
|
||
n_y = 1 if len(y.shape) == 1 else y.shape[1] | ||
n_alphas = 1 if np.ndim(self.alphas) == 0 else len(self.alphas) | ||
|
||
|
@@ -2190,7 +2188,7 @@ def fit(self, X, y, sample_weight=None, score_params=None): | |
|
||
for i, alpha in enumerate(np.atleast_1d(self.alphas)): | ||
G_inverse_diag, c = solve(float(alpha), y, sqrt_sw, X_mean, *decomposition) | ||
if scorer is None: | ||
if self.scoring is None: | ||
squared_errors = (c / G_inverse_diag) ** 2 | ||
alpha_score = self._score_without_scorer(squared_errors=squared_errors) | ||
if self.store_cv_results: | ||
|
@@ -2213,7 +2211,7 @@ def fit(self, X, y, sample_weight=None, score_params=None): | |
predictions=predictions, | ||
y=unscaled_y, | ||
n_y=n_y, | ||
scorer=scorer, | ||
scorer=self.scoring, | ||
score_params=score_params, | ||
) | ||
|
||
|
@@ -2258,9 +2256,6 @@ def fit(self, X, y, sample_weight=None, score_params=None): | |
|
||
return self | ||
|
||
def _get_scorer(self): | ||
return check_scoring(self, scoring=self.scoring, allow_none=True) | ||
|
||
def _score_without_scorer(self, squared_errors): | ||
"""Performs scoring using squared errors when the scorer is None.""" | ||
if self.alpha_per_target: | ||
|
@@ -2382,6 +2377,7 @@ def fit(self, X, y, sample_weight=None, **params): | |
""" | ||
_raise_for_params(params, self, "fit") | ||
cv = self.cv | ||
scorer = self._get_scorer() | ||
|
||
# TODO(1.7): Remove in 1.7 | ||
# Also change `store_cv_results` default back to False | ||
|
@@ -2445,10 +2441,14 @@ def fit(self, X, y, sample_weight=None, **params): | |
if sample_weight is not None: | ||
routed_params.scorer.score["sample_weight"] = sample_weight | ||
|
||
# reset `scorer` variable to original user-intend if no scoring is passed | ||
if self.scoring is None: | ||
scorer = None | ||
Comment on lines
+2445
to
+2446
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I should be missing something. Why we would not combine the above call in the same statement? if self.scoring is not None:
scorer = self._get_scorer()
else:
scorer = None Or is it because we want still to set the score_request but in which case I would expect scorer = self._get_scorer()
if self.scoring is None:
scorer = None I would probably add a small comment on the top to explain we do this procedure to avoid someone reverting to the first version. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for looking into this. I am not sure if I understand what you mean, @glemaitre. I will try to explain what I meant: We have to call So the code needs to be like this:
The scorer needs to be defined ( But then below we need to reset
If we would not do that, we would get an Basically, we are misusing the variable I have added a comment to explain what I mean. Does it all make sense? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes completely. I missed that we were going to get the combination of I think we can merge as-is. Maybe one clean-up could be to check that we get an |
||
|
||
estimator = _RidgeGCV( | ||
alphas, | ||
fit_intercept=self.fit_intercept, | ||
scoring=self.scoring, | ||
scoring=scorer, | ||
gcv_mode=self.gcv_mode, | ||
store_cv_results=self._store_cv_results, | ||
is_clf=is_classifier(self), | ||
|
@@ -2484,7 +2484,7 @@ def fit(self, X, y, sample_weight=None, **params): | |
estimator, | ||
parameters, | ||
cv=cv, | ||
scoring=self.scoring, | ||
scoring=scorer, | ||
) | ||
|
||
grid_search.fit(X, y, **params) | ||
|
@@ -2518,14 +2518,25 @@ def get_metadata_routing(self): | |
MetadataRouter(owner=self.__class__.__name__) | ||
.add_self_request(self) | ||
.add( | ||
scorer=self._get_scorer(), | ||
method_mapping=MethodMapping().add(callee="score", caller="fit"), | ||
scorer=self.scoring, | ||
method_mapping=MethodMapping().add(caller="fit", callee="score"), | ||
) | ||
.add( | ||
splitter=self.cv, | ||
method_mapping=MethodMapping().add(caller="fit", callee="split"), | ||
) | ||
) | ||
return router | ||
|
||
def _get_scorer(self): | ||
return check_scoring(self, scoring=self.scoring, allow_none=True) | ||
scorer = check_scoring(estimator=self, scoring=self.scoring, allow_none=True) | ||
if _routing_enabled() and self.scoring is None: | ||
# This estimator passes an array of 1s as sample_weight even if | ||
# sample_weight is not provided by the user. Therefore we need to | ||
# always request it. But we don't set it if it's passed explicitly | ||
# by the user. | ||
scorer.set_score_request(sample_weight=True) | ||
return scorer | ||
|
||
# TODO(1.7): Remove | ||
# mypy error: Decorated property not supported | ||
|
Uh oh!
There was an error while loading. Please reload this page.