Source code for catalyst.utils.metrics.iou
"""
IoU metric. Jaccard metric refers to IoU here, same functionality.
"""
from typing import List, Union
from functools import partial
import torch
from catalyst.utils.torch import get_activation_fn
[docs]def iou(
outputs: torch.Tensor,
targets: torch.Tensor,
# values are discarded, only None check
# used for compatibility with MultiMetricCallback
classes: List[str] = None,
eps: float = 1e-7,
threshold: float = None,
activation: str = "Sigmoid",
) -> Union[float, List[float]]:
"""
Args:
outputs (torch.Tensor): A list of predicted elements
targets (torch.Tensor): A list of elements that are to be predicted
eps (float): epsilon to avoid zero division
threshold (float): threshold for outputs binarization
activation (str): An torch.nn activation applied to the outputs.
Must be one of ["none", "Sigmoid", "Softmax2d"]
Returns:
Union[float, List[float]]: IoU (Jaccard) score(s)
"""
activation_fn = get_activation_fn(activation)
outputs = activation_fn(outputs)
if threshold is not None:
outputs = (outputs > threshold).float()
# ! fix backward compatibility
if classes is not None:
# if classes are specified we reduce across all dims except channels
_sum = partial(torch.sum, dim=[0, 2, 3])
else:
_sum = torch.sum
intersection = _sum(targets * outputs)
union = _sum(targets) + _sum(outputs)
# this looks a bit awkward but `eps * (union == 0)` term
# makes sure that if I and U are both 0, than IoU == 1
# and if U != 0 and I == 0 the eps term in numerator is zeroed out
# i.e. (0 + eps) / (U - 0 + eps) doesn't happen
iou = (intersection + eps * (union == 0)) / (union - intersection + eps)
return iou
jaccard = iou
__all__ = ["iou", "jaccard"]