Skip to content

Fix CohenKappa ignoring sample weights#1956

Open
chuenchen309 wants to merge 1 commit into
online-ml:mainfrom
chuenchen309:hunt/river-a1
Open

Fix CohenKappa ignoring sample weights#1956
chuenchen309 wants to merge 1 commit into
online-ml:mainfrom
chuenchen309:hunt/river-a1

Conversation

@chuenchen309

Copy link
Copy Markdown
Contributor

CohenKappa.get() divides the observed agreement (p0) and the two expected-agreement estimators by self.cm.n_samples — the raw, unweighted observation count — while the numerators (total_true_positives, sum_row[c], sum_col[c]) are all weighted sums. When any sample weight differs from 1, the denominator no longer matches the numerator and the returned Kappa is wrong. With unit weights n_samples == total_weight, which is why the existing tests never caught it.

CohenKappa inherits works_with_weights == True (the base default) and is driven through the documented update(y_true, y_pred, w=...) weight entry point, so it advertises weight support while computing the wrong number. The sibling metrics that genuinely can't handle weights (mutual_info, vbeta, rand, fowlkes_mallows) all override works_with_weights = False; and Accuracy.get() — which the in-line comment says CohenKappa's p0 is "same as" — already divides by total_weight.

Fix: divide the three agreement terms in get() by self.cm.total_weight instead of self.cm.n_samples.

Verification (re-runnable from the diff):

  • New test test_cohen_kappa_supports_sample_weight asserts equality with sklearn.metrics.cohen_kappa_score(..., sample_weight=...) and that the weighted result differs from the unweighted one (proving the weight is actually consumed). It is red before the change and green after.
  • Full river/metrics/ suite + doctests: 278 passed.
  • Oracle cross-checked against sklearn on the fixed case, the unweighted case, and 500 random weighted fuzz cases (0 mismatches; degenerate single-label windows yield nan in both and are excluded).

This PR was authored by an AI coding agent (Claude Code) running on this account: the AI found the bug, ran the repro, wrote the tests, and wrote this description. The human account holder reviews every change and is accountable for it. The verification above is real and re-runnable from the diff. If this isn't the kind of contribution you want, say so and I'll close it.

CohenKappa.get() divided the observed-agreement and expected-agreement
terms by cm.n_samples (the raw observation count) instead of
cm.total_weight (the sum of sample weights), so any non-unit sample
weight produced a wrong score. Accuracy, which the code comment says it
mirrors, already uses total_weight. With all weights equal to 1 the two
are identical, which is why this went unnoticed.

Matches sklearn.metrics.cohen_kappa_score(..., sample_weight=...).

Signed-off-by: chuenchen309 <48723787+chuenchen309@users.noreply.github.com>
@MaxHalford

Copy link
Copy Markdown
Member

Hey there @chuenchen309! May I ask you to open issues instead of immediately proceed to a fix? I appreciate you discovering these bugs, but I would like to dissociate the bug report from the correction. Would that be acceptable for you?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants