def iou(
    outputs: torch.Tensor,
    targets: torch.Tensor,
    class_dim: int = 1,
    threshold: float = None,
    mode: str = "per-class",
    weights: Optional[List[float]] = None,
    eps: float = 1e-7,
) -> torch.Tensor:
    """
    Computes the iou/jaccard score,
    iou score = intersection / union = tp / (tp + fp + fn)

    Args:
        outputs: [N; K; ...] tensor that for each of the N examples
            indicates the probability of the example belonging to each of
            the K classes, according to the model.
        targets:  binary [N; K; ...] tensor that encodes which of the K
            classes are associated with the N-th input
        class_dim: indicates class dimention (K) for
            ``outputs`` and ``targets`` tensors (default = 1), if
            mode = "micro" means nothing
        threshold: threshold for outputs binarization
        mode: class summation strategy. Must be one of ['micro', 'macro',
            'weighted', 'per-class']. If mode='micro', classes are ignored,
            and metric are calculated generally. If mode='macro', metric are
            calculated per-class and than are averaged over all classes. If
            mode='weighted', metric are calculated per-class and than summed
            over all classes with weights. If mode='per-class', metric are
            calculated separately for all classes
        weights: class weights(for mode="weighted")
        eps: epsilon to avoid zero division

    Returns:
        IoU (Jaccard) score for each class(if mode='weighted') or aggregated IOU

    Example:

    .. code-block:: python

        import torch
        from catalyst import metrics

        size = 4
        half_size = size // 2
        shape = (1, 1, size, size)
        empty = torch.zeros(shape)
        full = torch.ones(shape)
        left = torch.ones(shape)
        left[:, :, :, half_size:] = 0
        right = torch.ones(shape)
        right[:, :, :, :half_size] = 0
        top_left = torch.zeros(shape)
        top_left[:, :, :half_size, :half_size] = 1
        pred = torch.cat([empty, left, empty, full, left, top_left], dim=1)
        targets = torch.cat([full, right, empty, full, left, left], dim=1)

        metrics.iou(
            outputs=pred,
            targets=targets,
            class_dim=1,
            threshold=0.5,
            mode="per-class"
        )
        # tensor([0.0000, 0.0000, 1.0000, 1.0000, 1.0000, 0.5])

        metrics.iou(
            outputs=pred,
            targets=targets,
            class_dim=1,
            threshold=0.5,
            mode="macro"
        )
        # tensor(0.5833)

        metrics.iou(
            outputs=pred,
            targets=targets,
            class_dim=1,
            threshold=0.5,
            mode="micro"
        )
        # tensor(0.4375)
    """
    metric_fn = partial(_iou, eps=eps)
    score = _get_region_based_metrics(
        outputs=outputs,
        targets=targets,
        metric_fn=metric_fn,
        class_dim=class_dim,
        threshold=threshold,
        mode=mode,
        weights=weights,
    )
    return score

    Computes the iou/jaccard score,
    iou score = intersection / union = tp / (tp + fp + fn)

    Args:
        outputs: [N; K; ...] tensor that for each of the N examples
            indicates the probability of the example belonging to each of
            the K classes, according to the model.
        targets:  binary [N; K; ...] tensor that encodes which of the K
            classes are associated with the N-th input
        class_dim: indicates class dimention (K) for
            ``outputs`` and ``targets`` tensors (default = 1), if
            mode = "micro" means nothing
        threshold: threshold for outputs binarization
        mode: class summation strategy. Must be one of ['micro', 'macro',
            'weighted', 'per-class']. If mode='micro', classes are ignored,
            and metric are calculated generally. If mode='macro', metric are
            calculated per-class and than are averaged over all classes. If
            mode='weighted', metric are calculated per-class and than summed
            over all classes with weights. If mode='per-class', metric are
            calculated separately for all classes
        weights: class weights(for mode="weighted")
        eps: epsilon to avoid zero division

    Returns:
        IoU (Jaccard) score for each class(if mode='weighted') or aggregated IOU

    Example:

    .. code-block:: python

        import torch
        from catalyst import metrics

        size = 4
        half_size = size // 2
        shape = (1, 1, size, size)
        empty = torch.zeros(shape)
        full = torch.ones(shape)
        left = torch.ones(shape)
        left[:, :, :, half_size:] = 0
        right = torch.ones(shape)
        right[:, :, :, :half_size] = 0
        top_left = torch.zeros(shape)
        top_left[:, :, :half_size, :half_size] = 1
        pred = torch.cat([empty, left, empty, full, left, top_left], dim=1)
        targets = torch.cat([full, right, empty, full, left, left], dim=1)

        metrics.iou(
            outputs=pred,
            targets=targets,
            class_dim=1,
            threshold=0.5,
            mode="per-class"
        )
        # tensor([0.0000, 0.0000, 1.0000, 1.0000, 1.0000, 0.5])

        metrics.iou(
            outputs=pred,
            targets=targets,
            class_dim=1,
            threshold=0.5,
            mode="macro"
        )
        # tensor(0.5833)

        metrics.iou(
            outputs=pred,
            targets=targets,
            class_dim=1,
            threshold=0.5,
            mode="micro"
        )
        # tensor(0.4375)
    
catalyst/metrics/functional/_segmentation.py