Skip to content
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

FEA Top k accuracy metric #16625

Merged
merged 83 commits into from
Oct 16, 2020
Merged

Conversation

gbolmier
Copy link
Contributor

@gbolmier gbolmier commented Mar 3, 2020

Reference Issues/PRs

Closes #10488
Fixes #10144
Fixes #8234

What does this implement/fix? Explain your changes.

This implements a top-k accuracy classification metric, for use with predicted class scores in multiclass classification settings. A prediction is considered top-k accurate if the correct class is one of the k classes with the highest predicted scores.

Copy link
Member

@NicolasHug NicolasHug left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @gbolmier , a few comments ;)

sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/_ranking.py Show resolved Hide resolved
sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
@gbolmier gbolmier changed the title Top k accuracy metric [MRG] Top k accuracy metric Mar 3, 2020
Raise errors for `k`=1, `k`=`n_classes`, cover binary `y_true` as it can be a subset of the possible classes, fix doc and update tests and doctest to match changes
@gbolmier
Copy link
Contributor Author

gbolmier commented Mar 3, 2020

Thank you so much for taking the time of the review @NicolasHug!
Let me know if there is more to improve :)

Add test for case when `y_true` = [0]*4
Copy link
Member

@NicolasHug NicolasHug left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @gbolmier a few more.

Let's also add a small section in the User Guide!

sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
@@ -1419,3 +1419,94 @@ def ndcg_score(y_true, y_score, k=None, sample_weight=None, ignore_ties=False):
_check_dcg_target_type(y_true)
gain = _ndcg_sample_scores(y_true, y_score, k=k, ignore_ties=ignore_ties)
return np.average(gain, weights=sample_weight)


def top_k_accuracy_score(y_true, y_score, k=5, normalize=True):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about the default, should it be 2, e.g. the minimum value for which the function can be called? It would work in all cases. 5 would fail if n_classes < 5

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with that!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure that we want ValueError here. I believe that for k>=n_classes we should raise a warning with the same message probably but we probably want to return a score. No?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should raise an error if k >= n_classes. This will always output an accuracy of 1 which will lure inexperienced users into thinking their estimator is doing great, where in reality they're just misusing a metric.

In general, we try to make misuses hard / impossible

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, we try to make misuses hard / impossible

Agree.

will lure inexperienced users into thinking their estimator is doing great

If they have a binary problem and they ask for top_5 accuracy then their estimator will be doing great obviously!

I dunno. IMHO a warning is enough.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If they have a binary problem and they ask for top_5 accuracy then their estimator will be doing great obviously!

Indeed. Also +1 to increase the default to at least 3. I think top_5 is good when you have a very large number of classes (e.g. ImageNet), but 30-60 classes which is more common with tabular data, top_3 is already quite useful.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If they have a binary problem and they ask for top_5 accuracy then their estimator will be doing great obviously!

Obvious to you, maybe not to them. Also note that we error in the binary case too.

sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/_ranking.py Show resolved Hide resolved
sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/tests/test_ranking.py Outdated Show resolved Hide resolved
gbolmier and others added 6 commits March 3, 2020 17:42
Co-Authored-By: Nicolas Hug <contact@nicolas-hug.com>
Co-Authored-By: Nicolas Hug <contact@nicolas-hug.com>
Change `k` default to 2. Update docstring and error msg
sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
@chkoar
Copy link
Contributor

chkoar commented Mar 4, 2020

Don't we want a default scorer for that metric? I understand that k might be blocker for that, though.

Add `y_true = [0]*5` case
Add `normalize == False` case
Change `k` default to 3 as it represents better the usual case. Make `y_true` value error message more explicit. Check `y_score` number of columns. Fix `k` check with n_classes
@gbolmier
Copy link
Contributor Author

Should be better like that @jnothman

Copy link
Member

@rth rth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your work and patience @gbolmier, a few more minor comments below otherwise looks good.

Also please add it to https://scikit-learn.org/stable/modules/model_evaluation.html#common-cases-predefined-values

sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/_ranking.py Outdated Show resolved Hide resolved
sklearn/metrics/tests/test_common.py Outdated Show resolved Hide resolved
# More detailed explanatory text, if necessary. Wrap it to about 72
# characters or so. In some contexts, the first line is treated as the
# subject of the commit and the rest of the text as the body. The
# blank line separating the summary from the body is critical (unless
# you omit the body entirely); various tools like `log`, `shortlog`
# and `rebase` can get confused if you run the two together.

# Explain the problem that this commit is solving. Focus on why you
# are making this change as opposed to how (the code explains that).
# Are there side effects or other unintuitive consequences of this
# change? Here's the place to explain them.

# Further paragraphs come after blank lines.

#  - Bullet points are okay, too

#  - Typically a hyphen or asterisk is used for the bullet, preceded
#    by a single space, with blank lines in between, but conventions
#    vary here

# If you use an issue tracker, put references to them at the bottom,
# like this:

# Resolves: scikit-learn#123
# See also: scikit-learn#456, scikit-learn#789
# More detailed explanatory text, if necessary. Wrap it to about 72
# characters or so. In some contexts, the first line is treated as the
# subject of the commit and the rest of the text as the body. The
# blank line separating the summary from the body is critical (unless
# you omit the body entirely); various tools like `log`, `shortlog`
# and `rebase` can get confused if you run the two together.

# Explain the problem that this commit is solving. Focus on why you
# are making this change as opposed to how (the code explains that).
# Are there side effects or other unintuitive consequences of this
# change? Here's the place to explain them.

# Further paragraphs come after blank lines.

#  - Bullet points are okay, too

#  - Typically a hyphen or asterisk is used for the bullet, preceded
#    by a single space, with blank lines in between, but conventions
#    vary here

# If you use an issue tracker, put references to them at the bottom,
# like this:

# Resolves: scikit-learn#123
# See also: scikit-learn#456, scikit-learn#789
# More detailed explanatory text, if necessary. Wrap it to about 72
# characters or so. In some contexts, the first line is treated as the
# subject of the commit and the rest of the text as the body. The
# blank line separating the summary from the body is critical (unless
# you omit the body entirely); various tools like `log`, `shortlog`
# and `rebase` can get confused if you run the two together.

# Explain the problem that this commit is solving. Focus on why you
# are making this change as opposed to how (the code explains that).
# Are there side effects or other unintuitive consequences of this
# change? Here's the place to explain them.

# Further paragraphs come after blank lines.

#  - Bullet points are okay, too

#  - Typically a hyphen or asterisk is used for the bullet, preceded
#    by a single space, with blank lines in between, but conventions
#    vary here

# If you use an issue tracker, put references to them at the bottom,
# like this:

# Resolves: scikit-learn#123
# See also: scikit-learn#456, scikit-learn#789
@gbolmier
Copy link
Contributor Author

gbolmier commented Aug 9, 2020

Thanks for your work and patience @gbolmier, a few more minor comments below otherwise looks good.

This is how you learn the ropes :), thanks a lot for the review @rth! Let me know if it needs any other changes

Copy link
Member

@rth rth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @gbolmier! LGTM. Should be good to merge unless anyone has more comments?

@jnothman I think you review comments were addressed.

@cmarmo
Copy link
Contributor

cmarmo commented Sep 24, 2020

Hi @jnothman, do you mind checking if your comments have been addressed? Two approvals here already. Thanks for your time.

@cmarmo
Copy link
Contributor

cmarmo commented Oct 15, 2020

Two approvals here! Time to merge?

@rth
Copy link
Member

rth commented Oct 16, 2020

Merging thanks again @gbolmier ! Also thank you for the follow up @cmarmo !

@rth rth changed the title [MRG] Top k accuracy metric FEA Top k accuracy metric Oct 16, 2020
@rth rth merged commit 5654da0 into scikit-learn:master Oct 16, 2020
@jnothman
Copy link
Member

jnothman commented Oct 17, 2020 via email

amrcode pushed a commit to amrcode/scikit-learn that referenced this pull request Oct 19, 2020
Co-authored-by: Nicolas Hug <contact@nicolas-hug.com>
Co-authored-by: Jeremiah Johnson <jwjohnson314@gmail.com>
Co-authored-by: Roman Yurchak <rth.yurchak@gmail.com>
jayzed82 pushed a commit to jayzed82/scikit-learn that referenced this pull request Oct 22, 2020
Co-authored-by: Nicolas Hug <contact@nicolas-hug.com>
Co-authored-by: Jeremiah Johnson <jwjohnson314@gmail.com>
Co-authored-by: Roman Yurchak <rth.yurchak@gmail.com>
@gbolmier gbolmier deleted the top_k_accuracy_metric branch November 14, 2020 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add top K error into scikit-learn