-
-
Notifications
You must be signed in to change notification settings - Fork 25.9k
[MRG + 2] Rename scorers like mse
to neg_mse
#7261
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
Conversation
mse
to neg_mse
mse
to neg_mse
Rename scorers like MSE to neg_MSE so that it is less surprising that they return negative values.
mse
to neg_mse
mse
to neg_mse
get_scrorer now warns if you use an old name for a scorer and tests have been updated to use new naming convention.
mean_absolute_error_scorer = make_scorer(mean_absolute_error, | ||
greater_is_better=False) | ||
median_absolute_error_scorer = make_scorer(median_absolute_error, | ||
greater_is_better=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.
Because those variables do not have a leading _
the can unfortunately be considered public API even if not in the documentation. I think we should maintain backward compat aliases until 0.20:
# Backward compat alias to keep until the end of the deprecation period (0.20)
mean_squared_error_scorer = neg_mean_squared_error_scorer
mean_absolute_error_scorer = neg_mean_absolute_error_scorer
median_absolute_error_scorer = neg_median_absolute_error_scorer
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.
Maybe we could add a deprecation_msg
option to make_scorer
to make sure that the deprecation warning is raised when the user actually call the scorer instead of raising the warning in get_scorer
that only covers a subset of the public API.
neg_median_absolute_error_scorer = make_scorer(median_absolute_error,
greater_is_better=False)
median_absolute_error_scorer = make_scorer(
median_absolute_error,
greater_is_better=False,
deprecation_msg='Scoring method median_absolute_error was renamed to '
'neg_median_absolute_error in version 0.18 and will be '
'removed in 0.20.'
)
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.
why not deprecated(make_scorer(median_absolute_error, greater_is_better=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.
Ah, it's an object, not a function, so it doesn't go into the right branch in deprecated, right? We could still wrap the __call__
method, right?
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.
deprecated("message")._decorate_fun(make_scorer(median_absolute_error, greater_is_better=False))
seems to be the right solution imho.
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.
Neither of the deprecated()._decorate_*
work because make_scorer
doesn't return a class nor a function :-/ To get the __name__
of a class instance you have to do obj.__class__.__name__
.
I like handling the deprecation stuff as a wrapper instead of extra argument. I made a first proposal in 09cd4c7. It still has a few problems but it would allow you to do:
deprecated('hello')(make_scorer(median_absolute_error, greater_is_better=False))
This will however print Thing _PredictScorer in deprecated...
and I think it will be quite hard to find out the correct name to print in a generic way inside deprecated()
... but do we want to cook something that is special to handling make_scorer
??
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 would rather avoid making the sklearn.utils.deprecation.deprecated
wrapper too complex. I think it's good enough to not use it at all in this case and just use a _deprecation_msg
attribute on _BaseScorer
as suggested in #7261 (comment).
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 wouldn't want to make the wrapper to complex, but I feel that deprecating the call method is really the easiest thing. We also don't need to change the wrapper for that. It will then say __call__
is deprecated and we can let the message explain that.
Maintain old names during the deprecation period and update tests to use better variables names.
There is a failed doctest in https://travis-ci.org/scikit-learn/scikit-learn/jobs/155644998#L3998 |
Also line 204 of |
Thanks. I had updated the expected output but not the actual code ... both fixed now. |
median_absolute_error=median_absolute_error_scorer, | ||
mean_absolute_error=mean_absolute_error_scorer, | ||
mean_squared_error=mean_squared_error_scorer, | ||
accuracy=accuracy_scorer, roc_auc=roc_auc_scorer, | ||
average_precision=average_precision_scorer, | ||
log_loss=log_loss_scorer, |
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.
we can't remove that, right? It's public API.
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.
Correct. Wasn't paying enough attention apparently :(
thanks for working on this, it's very important I think. |
Sorry I've not been attuned to this thread. As I've proposed before, I think all deprecation should be in |
Hm the scorer objects don't have underscores in their names, and the SCORERS dict that contains the instances is mentioned in the docs. I considered them public API. |
|
Treat (callable) instances different from functions in the deprecated decorator
My original implementation was via I think if we can organise for those users to get a warning as well without too much acrobatics then we should. No opinion on whether that warning should be the rename deprecation warning or a "stop using these internals" warning. |
@@ -33,14 +34,15 @@ | |||
|
|||
|
|||
class _BaseScorer(six.with_metaclass(ABCMeta, object)): | |||
def __init__(self, score_func, sign, kwargs): | |||
def __init__(self, score_func, sign, kwargs, deprecation_msg=None): |
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 think that we will want to get rid of the "deprecation_msg" in two release. Maybe add a comment here saying that this should be removed for 0.20.
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.
Maybe we could rename that parameter to _deprecation_msg
to make it explicit that this is not public API.
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.
Or even not put _deprecation_msg
in the __init__
at all but just as None
initialized attribute on the _BaseScorer
class and manually use
mean_scorer_error._deprecation_msg = "the message"
to activate the deprecation.
I've finished my pass. I am 👍 with this PR once my small remarks are addressed. Also, flake8 is unhappy (check travis). I guess that you should address that. |
|
||
@abstractmethod |
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 think you can keep this.
bump |
:) |
Examples not yet updated?
|
The fix it-self looks good to me. +1 for merge once the examples are updated. |
Updated. |
|
||
plt.plot(train_sizes, test_scores_svr.mean(1), 'o-', color="r", | ||
plt.plot(train_sizes, -test_scores_svr.mean(1), 'o-', color="r", |
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 think you should leave off this negation and change the ylabel to say "Negative".
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.
But what you have here is okay; better than what's currently plotted at http://scikit-learn.org/stable/auto_examples/plot_kernel_ridge_regression.html.
@ogrisel, any preference for plotting -MSE vs plotting MSE?
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 find plotting MSE and seeing it decrease easier on my brain than having to think "error, smaller is better but here it is negated so going up means closer to zero ..."
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.
The question from my perspective is whether it's worth encouraging users to negate output. Or whether, regardless of scoring function we'd like to encourage the convention that better is up.
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 have no opinion on this beyond previous comment. Who is going to arbitrate/decide?
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.
No strong opinion here. I'm fine with the -
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.
Merge then?
LGTM other than that too |
mse
to neg_mse
mse
to neg_mse
@betatim bonus points if you feel like tackling my comment from a week ago which got lost in other (very likely more important) considerations. |
Tested. I skipped testing the |
merge? |
Make it so. |
Yey! (I didn't do much, but I pressed the green button. What a pleasure!) |
Thanks heaps @betatim ! |
awesome, thanks! this was was overdue |
Thanks a lot for all the comments and extra 👀! |
Yay 🍻 Much needed PR! |
It does. Closed those. Thanks @raghavrv |
Reference Issue
Fixes #2439
What does this implement/fix? Explain your changes.
Renaming scorers for which smaller is better (like MSE) to
neg_mse
so that they fit the idea of "bigger is better".mean_squared_error
mean_absolute_error
log_loss
median_absolute_error