Skip to content

Commit

Permalink
5381 and deprecate compute_meandice compute_meaniou (#5382)
Browse files Browse the repository at this point in the history
Signed-off-by: Wenqi Li <[email protected]>

Fixes #5381

- non-breaking changes to rename `compute_meandice` to `compute_dice`
- non-breaking changes to rename `compute_meaniou` to `compute_iou`

<!--- Put an `x` in all the boxes that apply, and remove the not
applicable items -->
- [x] Non-breaking change (fix or new feature that would not break
existing functionality).
- [ ] Breaking change (fix or new feature that would cause existing
functionality to change).
- [x] New tests added to cover the changes.
- [ ] Integration tests passed locally by running `./runtests.sh -f -u
--net --coverage`.
- [x] Quick tests passed locally by running `./runtests.sh --quick
--unittests --disttests`.
- [ ] In-line docstrings updated.
- [ ] Documentation updated, tested `make html` command in the `docs/`
folder.

Signed-off-by: Wenqi Li <[email protected]>
  • Loading branch information
wyli committed Oct 24, 2022
1 parent bc09a4c commit 8271a19
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 18 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
* Automatically infer device from the first item in random elastic deformation dict
* Add channel dim in `ComputeHoVerMaps` and `ComputeHoVerMapsd`
* Remove batch dim in `SobelGradients` and `SobelGradientsd`
### Deprecated
* Deprecating `compute_meandice`, `compute_meaniou` in `monai.metrics`, in favor of
`compute_dice` and `compute_iou` respectively

## [1.0.0] - 2022-09-16
### Added
Expand Down
4 changes: 2 additions & 2 deletions monai/metrics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
from .froc import compute_fp_tp_probs, compute_froc_curve_data, compute_froc_score
from .generalized_dice import GeneralizedDiceScore, compute_generalized_dice
from .hausdorff_distance import HausdorffDistanceMetric, compute_hausdorff_distance, compute_percent_hausdorff_distance
from .meandice import DiceMetric, compute_meandice
from .meaniou import MeanIoU, compute_meaniou
from .meandice import DiceMetric, compute_dice, compute_meandice
from .meaniou import MeanIoU, compute_iou, compute_meaniou
from .metric import Cumulative, CumulativeIterationMetric, IterationMetric, Metric
from .regression import MAEMetric, MSEMetric, PSNRMetric, RMSEMetric, SSIMMetric
from .rocauc import ROCAUCMetric, compute_roc_auc
Expand Down
2 changes: 1 addition & 1 deletion monai/metrics/active_learning_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

class VarianceMetric(Metric):
"""
Compute the Variance of a given T-repeats N-dimensional array/tensor. The primary usage is as a uncertainty based
Compute the Variance of a given T-repeats N-dimensional array/tensor. The primary usage is as an uncertainty based
metric for Active Learning.
It can return the spatial variance/uncertainty map based on user choice or a single scalar value via mean/sum of the
Expand Down
15 changes: 10 additions & 5 deletions monai/metrics/meandice.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import torch

from monai.metrics.utils import do_metric_reduction, ignore_background, is_binary_tensor
from monai.utils import MetricReduction
from monai.utils import MetricReduction, deprecated

from .metric import CumulativeIterationMetric

Expand Down Expand Up @@ -80,7 +80,7 @@ def _compute_tensor(self, y_pred: torch.Tensor, y: torch.Tensor): # type: ignor
if dims < 3:
raise ValueError(f"y_pred should have at least 3 dimensions (batch, channel, spatial), got {dims}.")
# compute dice (BxC) for each channel for each batch
return compute_meandice(
return compute_dice(
y_pred=y_pred, y=y, include_background=self.include_background, ignore_empty=self.ignore_empty
)

Expand All @@ -103,10 +103,10 @@ def aggregate(self, reduction: Union[MetricReduction, str, None] = None):
return (f, not_nans) if self.get_not_nans else f


def compute_meandice(
def compute_dice(
y_pred: torch.Tensor, y: torch.Tensor, include_background: bool = True, ignore_empty: bool = True
) -> torch.Tensor:
"""Computes Dice score metric from full size Tensor and collects average.
"""Computes Dice score metric for a batch of predictions.
Args:
y_pred: input data to compute, typical segmentation model output.
Expand Down Expand Up @@ -146,6 +146,11 @@ def compute_meandice(
y_pred_o = torch.sum(y_pred, dim=reduce_axis)
denominator = y_o + y_pred_o

if ignore_empty is True:
if ignore_empty:
return torch.where(y_o > 0, (2.0 * intersection) / denominator, torch.tensor(float("nan"), device=y_o.device))
return torch.where(denominator > 0, (2.0 * intersection) / denominator, torch.tensor(1.0, device=y_o.device))


@deprecated(since="1.0.0", msg_suffix="use `compute_dice` instead.")
def compute_meandice(*args, **kwargs):
return compute_dice(*args, **kwargs)
18 changes: 12 additions & 6 deletions monai/metrics/meaniou.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
import torch

from monai.metrics.utils import do_metric_reduction, ignore_background, is_binary_tensor
from monai.utils import MetricReduction
from monai.utils import MetricReduction, deprecated

from .metric import CumulativeIterationMetric


class MeanIoU(CumulativeIterationMetric):
"""
Compute average IoU score between two tensors. It can support both multi-classes and multi-labels tasks.
Compute average Intersection over Union (IoU) score between two tensors.
It supports both multi-classes and multi-labels tasks.
Input `y_pred` is compared with ground truth `y`.
`y_pred` is expected to have binarized predictions and `y` should be in one-hot format. You can use suitable transforms
in ``monai.transforms.post`` first to achieve binarized values.
Expand Down Expand Up @@ -80,7 +81,7 @@ def _compute_tensor(self, y_pred: torch.Tensor, y: torch.Tensor): # type: ignor
if dims < 3:
raise ValueError(f"y_pred should have at least 3 dimensions (batch, channel, spatial), got {dims}.")
# compute IoU (BxC) for each channel for each batch
return compute_meaniou(
return compute_iou(
y_pred=y_pred, y=y, include_background=self.include_background, ignore_empty=self.ignore_empty
)

Expand All @@ -103,10 +104,10 @@ def aggregate(self, reduction: Union[MetricReduction, str, None] = None):
return (f, not_nans) if self.get_not_nans else f


def compute_meaniou(
def compute_iou(
y_pred: torch.Tensor, y: torch.Tensor, include_background: bool = True, ignore_empty: bool = True
) -> torch.Tensor:
"""Computes IoU score metric from full size Tensor and collects average.
"""Computes Intersection over Union (IoU) score metric from a batch of predictions.
Args:
y_pred: input data to compute, typical segmentation model output.
Expand Down Expand Up @@ -146,6 +147,11 @@ def compute_meaniou(
y_pred_o = torch.sum(y_pred, dim=reduce_axis)
union = y_o + y_pred_o - intersection

if ignore_empty is True:
if ignore_empty:
return torch.where(y_o > 0, (intersection) / union, torch.tensor(float("nan"), device=y_o.device))
return torch.where(union > 0, (intersection) / union, torch.tensor(1.0, device=y_o.device))


@deprecated(since="1.0.0", msg_suffix="use `compute_iou` instead.")
def compute_meaniou(*args, **kwargs):
return compute_iou(*args, **kwargs)
4 changes: 2 additions & 2 deletions tests/test_compute_meandice.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import torch
from parameterized import parameterized

from monai.metrics import DiceMetric, compute_meandice
from monai.metrics import DiceMetric, compute_dice, compute_meandice

_device = "cuda:0" if torch.cuda.is_available() else "cpu"
# keep background
Expand Down Expand Up @@ -187,7 +187,7 @@
class TestComputeMeanDice(unittest.TestCase):
@parameterized.expand([TEST_CASE_1, TEST_CASE_2, TEST_CASE_9, TEST_CASE_11, TEST_CASE_12])
def test_value(self, input_data, expected_value):
result = compute_meandice(**input_data)
result = compute_dice(**input_data)
np.testing.assert_allclose(result.cpu().numpy(), expected_value, atol=1e-4)

@parameterized.expand([TEST_CASE_3])
Expand Down
4 changes: 2 additions & 2 deletions tests/test_compute_meaniou.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import torch
from parameterized import parameterized

from monai.metrics import MeanIoU, compute_meaniou
from monai.metrics import MeanIoU, compute_iou, compute_meaniou

_device = "cuda:0" if torch.cuda.is_available() else "cpu"
# keep background
Expand Down Expand Up @@ -192,7 +192,7 @@ def test_value(self, input_data, expected_value):

@parameterized.expand([TEST_CASE_3])
def test_nans(self, input_data, expected_value):
result = compute_meaniou(**input_data)
result = compute_iou(**input_data)
self.assertTrue(np.allclose(np.isnan(result.cpu().numpy()), expected_value))

# MeanIoU class tests
Expand Down

0 comments on commit 8271a19

Please sign in to comment.