From 8302300bd7fb391cfcea172c2ddbe777bf881ea7 Mon Sep 17 00:00:00 2001 From: rittik9 Date: Mon, 9 Sep 2024 17:16:59 +0530 Subject: [PATCH 1/2] Fix: Handle zero division error in binary IoU (Jaccard index) calculation --- .../functional/classification/jaccard.py | 2 +- .../unittests/classification/test_jaccard.py | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/torchmetrics/functional/classification/jaccard.py b/src/torchmetrics/functional/classification/jaccard.py index 1d240df68af..dfddd68255f 100644 --- a/src/torchmetrics/functional/classification/jaccard.py +++ b/src/torchmetrics/functional/classification/jaccard.py @@ -67,7 +67,7 @@ def _jaccard_index_reduce( raise ValueError(f"The `average` has to be one of {allowed_average}, got {average}.") confmat = confmat.float() if average == "binary": - return confmat[1, 1] / (confmat[0, 1] + confmat[1, 0] + confmat[1, 1]) + return _safe_divide(confmat[1, 1], (confmat[0, 1] + confmat[1, 0] + confmat[1, 1]), zero_division=zero_division) ignore_index_cond = ignore_index is not None and 0 <= ignore_index < confmat.shape[0] multilabel = confmat.ndim == 3 diff --git a/tests/unittests/classification/test_jaccard.py b/tests/unittests/classification/test_jaccard.py index 6901868eac9..e7afdb557a6 100644 --- a/tests/unittests/classification/test_jaccard.py +++ b/tests/unittests/classification/test_jaccard.py @@ -26,6 +26,7 @@ MultilabelJaccardIndex, ) from torchmetrics.functional.classification.jaccard import ( + _jaccard_index_reduce, binary_jaccard_index, multiclass_jaccard_index, multilabel_jaccard_index, @@ -403,6 +404,26 @@ def test_corner_case(): assert torch.allclose(res, out) +def test_jaccard_index_zero_division(): + """Issue: https://github.com/Lightning-AI/torchmetrics/issues/2658.""" + # Test case where all pixels are background (zeros) + confmat = torch.tensor([[4, 0], [0, 0]]) + + # Test with zero_division=0.0 + result = _jaccard_index_reduce(confmat, average="binary", zero_division=0.0) + assert result == 0.0, f"Expected 0.0, but got {result}" + + # Test with zero_division=1.0 + result = _jaccard_index_reduce(confmat, average="binary", zero_division=1.0) + assert result == 1.0, f"Expected 1.0, but got {result}" + + # Test case with some foreground pixels + confmat = torch.tensor([[2, 1], [1, 1]]) + result = _jaccard_index_reduce(confmat, average="binary", zero_division=0.0) + expected = 1 / 3 + assert torch.isclose(result, torch.tensor(expected)), f"Expected {expected}, but got {result}" + + @pytest.mark.parametrize( ("metric", "kwargs"), [ From 9098d0a02dd7481c016531cc7842ba4a0285617d Mon Sep 17 00:00:00 2001 From: Jirka Borovec <6035284+Borda@users.noreply.github.com> Date: Mon, 9 Sep 2024 19:38:53 +0200 Subject: [PATCH 2/2] chlog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b0b0022476..0e6d5f40643 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- +- Fixed handling zero division error in binary IoU (Jaccard index) calculation ([#2726](https://github.com/Lightning-AI/torchmetrics/pull/2726)) ## [1.4.1] - 2024-08-02