# dice_coefficient

Python API: `luxonis_train.attached_modules.metrics.dice_coefficient`

The Dice coefficient over segmentation masks.

## Classes

### DiceCoefficient

Dice coefficient metric for segmentation masks.

 * `Inputs:`: * `predictions` (`Tensor`): [B, nclasses, H, W] logits
    * `target` (`Tensor`): [B, nclasses, H, W] one-hot masks
 * `Outputs:`: * `Tensor`: scalar, or [nclasses] when `average` is `"none"` or `None`. Without the background class, the shape is
   [nclasses − 1]. A result with one element is a scalar.
 * `Formula:`: Each predicted pixel gets the class with the highest logit. For image i and class c, Pi, c is the set of predicted
   pixels and Ti, c the set of target pixels. The per-class score is: Di, c = (2|Pi, c∩Ti, c|)/(|Pi, c| + |Ti, c|) `average`
   combines the classes of each image. `"micro"` sums the numerators and the denominators of all classes before the division. The
   result is the mean over all images. A score with a zero denominator is `NaN`, and the means skip it.

> **References**
> * Source: Wraps [torchmetrics](https://github.com/Lightning-AI/torchmetrics) (Apache-2.0).
 * License: Apache-2.0 (this project)

> **Notes**
> When `average` is `"micro"`, the `DiceScore` constructor of `torchmetrics` warns about a future change of its default `average`. This class always passes `average`, so the warning does not apply.

> **Example**
> Attached to a `DDRNetSegmentationHead` in `model.nodes`:

```yaml
- name: DDRNetSegmentationHead
  inputs: [DDRNet]
  metrics:
    - name: DiceCoefficient
      params:
        num_classes: 2
```

 * `Compatible with:`: * Nodes: *
   [BiSeNetHead](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/nodes/heads/bisenet_head.md)
       * [DDRNetSegmentationHead](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/nodes/heads/ddrnet_segmentation_head.md)
       * [SegmentationHead](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/nodes/heads/segmentation_head.md)
       * [TransformerSegmentationHead](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/nodes/heads/transformer_segmentation_head.md)

#### Methods

##### init

```python
def __init__(num_classes: int, include_background: bool = True, average: Literal['micro', 'macro', 'weighted', 'none'] | None = 'micro', input_format: Literal['one-hot', 'index'] = 'index', **kwargs):
```

Initialize the metric and the wrapped `DiceScore`.

Parameters

 * `num_classes` (`int`): The number of classes, the size of the class dimension of the inputs.
 * `include_background` (`bool`): Whether class `0` counts. When `False`, the metric drops class `0` before it scores.
 * `average` (`Literal['micro', 'macro', 'weighted', 'none'] | None`): How the metric combines the classes of an image: *
   `"micro"`: one score from the summed counts of all classes.
    * `"macro"`: the mean of the per-class scores.
    * `"weighted"`: the per-class scores, weighted by the share of the target pixels of each class.
    * `"none"` or `None`: one score for each class.
 * `input_format` (`Literal['one-hot', 'index']`): How
   [update](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/dice_coefficient.md)
   converts the inputs, see
   [convert_format](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/dice_coefficient.md).
   The two formats give different results only for a target pixel with no class or with more than one class.
 * `**kwargs`: Keyword arguments forwarded to
   [BaseMetric](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/base_metric.md),
   such as `node`.

##### compute

```python
def compute(self) -> Tensor:
```

Return the Dice score of the images since the last reset.

> **Example**
> One image of four pixels. The target holds class `0` in the first two pixels and class `1` in the last two. The prediction is wrong in the second pixel. The `"micro"` average sums the numerators and the denominators of both classes: (2 + 4) ⁄ (3 + 5) = 0.75.

```pycon
>>> import torch
>>> target = torch.tensor([[[[1, 1, 0, 0]], [[0, 0, 1, 1]]]])
>>> logits = torch.tensor(
...     [[[[2.0, 0.0, 0.0, 0.0]], [[0.0, 1.0, 1.0, 1.0]]]]
... )
>>> metric = DiceCoefficient(num_classes=2)
>>> metric.update(logits, target)
>>> metric.compute().item()
0.75
```

Returns

 * `Tensor`: The mean score over the images, as a scalar. For `average` set to `"none"` or `None`, the mean score of each class,
   of shape `[C]`, or `[C - 1]` without the background class. A result with one element is a scalar.

##### convert_format

```python
def convert_format(tensor: Tensor, is_target: bool = False) -> Tensor:
```

Convert class scores to the format of `input_format`.

 * `"index"`: return the `argmax` over dimension `1`. The method does this for the target too, so a target pixel with no class
   becomes class `0`.
 * `"one-hot"`, with `is_target` set to `False`: return a one-hot tensor of the input shape and dtype. It holds `1` at the
   `argmax` class of each pixel.
 * `"one-hot"`, with `is_target` set to `True`: return `tensor` unchanged.

> **Examples**
> Logits of shape `[1, 2, 1, 2]` become class indices:

```pycon
>>> import torch
>>> logits = torch.tensor([[[[2.0, 0.0]], [[1.0, 3.0]]]])
>>> metric = DiceCoefficient(num_classes=2)
>>> metric.convert_format(logits).tolist()
[[[0, 1]]]
```

A target pixel with no class becomes class `0`:

```pycon
>>> empty = torch.zeros(1, 2, 1, 2)
>>> metric.convert_format(empty, is_target=True).tolist()
[[[0, 0]]]
```

Parameters

 * `tensor` (`Tensor`): Logits or masks of shape `[B, C, H, W]`.
 * `is_target` (`bool`): Whether `tensor` is the target.

Returns

 * `Tensor`: Class indices of shape `[B, H, W]` for `"index"`, otherwise a tensor of shape `[B, C, H, W]`.

##### reset

```python
def reset(self):
```

Reset the states of the wrapped `DiceScore`.

The method does not call the `reset` of `torchmetrics` for this metric. The cached result of the last
[compute](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/dice_coefficient.md)
stays, and
[compute](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/dice_coefficient.md)
returns it until the next
[update](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/dice_coefficient.md).

##### update

```python
def update(predictions: Tensor, target: Tensor):
```

Convert one batch and add it to the wrapped `DiceScore`.

For `"index"`,
[convert_format](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/metrics/dice_coefficient.md)
turns both tensors into class indices. For `"one-hot"`, it turns the predictions into one-hot masks, and the method casts both
tensors to `bool`. The wrapped metric stores the numerator, the denominator, and the number of target pixels of each image and
class.

Parameters

 * `predictions` (`Tensor`): Logits of shape `[B, C, H, W]`, the main output of the node.
 * `target` (`Tensor`): One-hot masks of shape `[B, C, H, W]`, the `segmentation` label of the task.

#### Attributes

##### metric

##### supported_tasks
