supervision/tests/metrics
Arthi Arumugam 7fc91180fe
fix(metrics): track prediction-only classes in Recall (#2468)
#2331 made Precision and F1Score include classes that appear only in
predictions, and added regression tests to both. Recall was not touched, so
the line #2331 replaced is still there and the three metrics disagree about
which classes exist for identical input:

    precision.matched_classes -> [0 1]   precision_per_class (2, 10)
    recall.matched_classes    -> [0]     recall_per_class    (1, 10)
    f1.matched_classes        -> [0 1]

These read as parallel outputs, so zipping them silently truncates rather
than raising.

Recall for a class with no ground-truth instances is 0.0 rather than
undefined, which is what sklearn reports (it infers labels from the union of
y_true and y_pred) and what #2331 cited as its own standard. MICRO is
unchanged because an absent class contributes no false negatives, and
WEIGHTED is unchanged because its ground-truth support is zero. MACRO does
change, and the changelog says so.

Also of note: recall.py already carried #2331's WEIGHTED zero-support guard,
whose comment refers to 'only false-positive classes'. That state could not
arise in recall.py, because unique_classes came from ground truth alone. The
guard was propagated; the union that gives it meaning was not.

Addresses the review on #2468. Building the class union inside
_compute_recall_for_classes only covers samples that reach it, and samples with
predictions but no targets are skipped earlier in _compute. So matched_classes
could still disagree with Precision and F1Score for list inputs containing a
background image, which is the exact invariant the new test asserts.

Before, for one normal sample plus one background image predicting class 2:

    precision.matched_classes -> [0 2]
    recall.matched_classes    -> [0]

Recall now handles len(targets) == 0 and len(predictions) > 0 the way Precision
does. No recall value changes, since a background image produces no false
negatives; only the tracked class set does.

* test: cover Recall bg-image size-bucket, dup & non-contiguous ids
* docs: strengthen Recall changelog migration note
* docs+perf: Recall doctest example; dedupe-then-union micro-opt

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
2026-08-03 20:57:05 +02:00
..
utils fix(metrics): ignore out-of-bucket detections in size-bucketed sco… (#2428) 2026-07-15 12:48:19 +02:00
__init__.py
conftest.py
test_core.py fix: close out remaining review findings (#2418) 2026-07-09 17:53:52 +02:00
test_detection.py feat(cv2): complete fallback integration (#2439) 2026-07-17 07:50:45 +02:00
test_f1_score.py fix(metrics): avoid division by zero RuntimeWarning in F1Score using np.divide (#2437) 2026-07-17 17:11:45 +02:00
test_lazy_imports.py fix: remaining review findings in dataset, docs, and tests (#2416) 2026-07-08 23:00:32 +02:00
test_mean_average_precision.py fix: close out remaining review findings (#2418) 2026-07-09 17:53:52 +02:00
test_mean_average_precision_area.py
test_mean_average_recall.py fix: close out remaining review findings (#2418) 2026-07-09 17:53:52 +02:00
test_oriented_bounding_box_metrics.py
test_precision.py fix: resolve medium dataset findings (#2408) 2026-07-08 08:56:34 +02:00
test_recall.py fix(metrics): track prediction-only classes in Recall (#2468) 2026-08-03 20:57:05 +02:00
test_size_bucket_regressions.py fix(metrics): ignore out-of-bucket detections in size-bucketed sco… (#2428) 2026-07-15 12:48:19 +02:00