8000 FIX f1_score with zero_division=1 on binary classes by OmarManzoor · Pull Request #27165 · scikit-learn/scikit-learn · GitHub
[go: up one dir, main page]

Skip to content

FIX f1_score with zero_division=1 on binary classes #27165

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

Closed
wants to merge 9 commits into from

Conversation

OmarManzoor
Copy link
Contributor

Reference Issues/PRs

Fixes #26965

What does this implement/fix? Explain your changes.

  • Fixes some incorrect behavior observed with f1 score on binary classfication inputs.

Any other comments?

CC: @glemaitre Could you kindly have a look to see if this makes sense? I am not totally sure this is the correct fix so marking the PR as draft.

@github-actions
Copy link
github-actions bot commented Aug 25, 2023

✔️ Linting Passed

All linting checks passed. Your pull request is in excellent shape! ☀️

Generated for commit: 612c77e. Link to the linter CI: here

pred_sum + true_sum, 0
)
denom[denom_mask] = 1 # avoid division by 0
f_score = numer / denom
Copy link
Member

Choose a reason for hiding this comment

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

Considering the issue reported in #27189, I think that we can express it without relying on the precision and recall:

# The score is defined as:
        # score = (1 + beta**2) * precision * recall / (beta**2 * precision + recall)
        # Therefore, you can express the score in terms of confusion matrix entries as:
        # score = (1 + beta**2) * tp / ((1 + beta**2) * tp + beta**2 * fn + fp)
        denom = beta2 * true_sum + pred_sum
        f_score = _prf_divide(
            (1 + beta2) * tp_sum,
            denom,
            "fscore",
            "true nor predicted",
            average,
            warn_for,
            zero_division,
        )

In this case, we handle it as any other by zero division.

Copy link
Member
@glemaitre glemaitre left a comment

Choose a reason for hiding this comment

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

The fix that I propose should solve the issue in #27189 and as well the original issue #26965

@glemaitre
Copy link
Member

The warning raise in _prf_divide is maybe wrong because the f1-score is not necessarly not defined now.

Copy link
Member

By using my proposed formulation, we have two tests that start to fail because instead of having the value provided by zero_division, we have an actual value.

@OmarManzoor OmarManzoor marked this pull request as ready for review September 18, 2023 07:32
@OmarManzoor
Copy link
Contributor Author

@glemaitre Should we remove the warning that we are specifically raising for f1

# warn for f-score only if zero_division is warn, it is in warn_for
    # and BOTH prec and rec are ill-defined
    if zero_division == "warn" and ("f-score",) == warn_for:
        if (pred_sum[true_sum == 0] == 0).any():
            _warn_prf(average, "true nor predicted", "F-score is", len(true_sum))

@glemaitre
Copy link
Member

Indeed since now the warning will be handled in the new _prf_divide. Previously if one of the precision or recall was undefined then, we could not provide a score which is not the case now. We just base it on the denominator only.

@glemaitre glemaitre self-requested a review October 11, 2023 19:14
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.

Wrong behaviour when calculating f1_score with zero_division=1
2 participants
0