# ohem_loss

Python API: `luxonis_train.attached_modules.losses.ohem_loss`

A loss wrapper that averages only the hardest elements.

## Classes

### OHEMLoss

Online hard example mining wrapper for pixel or class losses.

 * `Inputs:`: * `predictions` (`Tensor`): `[B, C, ...]` logits, passed to the criterion
    * `target` (`Tensor`): the label of the task, passed to the criterion
 * `Outputs:`: * `Tensor`: scalar
 * `Formula:`: The criterion computes the loss of each element, with `reduction="none"`. The loss sorts these n values in
   descending order, as ℓ0 ≥ ℓ1 ≥ …. With the ratio r = `ohem_ratio` and the probability p = `ohem_threshold`: k = min(⌊r n⌋, n −
   1), τ = − lnp When ℓk > τ, the loss is the mean of all values above τ. Otherwise, the loss is the mean of the k largest values.
   For a cross entropy without class weights and label smoothing, a value above τ means a predicted probability of the target
   below p.

> **References**
> * Source: This project.
 * License: Apache-2.0 (this project)

> **Notes**
> `criterion="auto"` selects [BCEWithLogitsLoss](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/losses/bce_with_logits.md) for a node with one class, and [CrossEntropyLoss](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/losses/cross_entropy.md) otherwise. The loss returns `nan` when k = 0 and ℓ0 ≤ τ, because the mean of no values is `nan`. For an input without elements, it returns the empty tensor of the element losses.

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

```yaml
- name: DDRNetSegmentationHead
  inputs: [DDRNet]
  losses:
    - name: OHEMLoss
```

 * `Compatible with:`: * Used by:
   [SegmentationModel](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/config/predefined_models/segmentation/v1/model.md)
    * Nodes: *
      [BiSeNetHead](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/nodes/heads/bisenet_head.md)
       * [ClassificationHead](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/nodes/heads/classification_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)
       * [TransformerClassificationHead](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/nodes/heads/transformer_classification_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__(criterion: str | type[BaseLoss] | Literal['auto'] = 'auto', ohem_ratio: float = 0.1, ohem_threshold: float = 0.7, **kwargs):
```

Initialize the loss and create the criterion.

The method creates the criterion with `**kwargs` and `reduction="none"`, so the criterion must accept `reduction`.

Parameters

 * `criterion` (`str | type[BaseLoss] | Literal['auto']`): The loss that computes the value of each element. A string names a loss
   in the
   [LOSSES](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/registry.md)
   registry, such as `"CrossEntropyLoss"`. An unknown name raises `KeyError`. The method uses a
   [BaseLoss](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/losses/base_loss.md)
   subclass as it is. `"auto"` selects `"BCEWithLogitsLoss"` when the node has one class, and `"CrossEntropyLoss"` otherwise. The
   method then logs a warning about the inferred task. Without a node, `"auto"` raises `ValueError`.
 * `ohem_ratio` (`float`): The ratio r that sets the number k of the largest values that the loss keeps when ℓk ≤ τ.
 * `ohem_threshold` (`float`): The probability p that sets the loss threshold τ = − lnp.
 * `**kwargs`: Keyword arguments forwarded to
   [BaseLoss](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/attached_modules/losses/base_loss.md)
   and to the criterion, such as `final_loss_weight` and `node`. Both receive the same arguments, so an argument that only the
   criterion accepts, such as `label_smoothing`, raises `TypeError`.

##### forward

```python
def forward(predictions: Tensor, target: Tensor) -> Tensor:
```

Compute the criterion loss and average the hardest elements.

The criterion gives the loss of each element. The method flattens these losses and keeps the hardest ones, as the class formula
describes.

> **Example**
> The four elements have the cross entropy `0.1269` or `2.1269`. With `ohem_ratio=0.5`, k is `2` and ℓ2 is `0.1269`. The default threshold gives τ = − ln0.7 ≈ 0.357, so the loss keeps the two largest values. The threshold `0.9` gives τ ≈ 0.105, so the loss keeps all values above it:

```pycon
>>> import torch
>>> logits = torch.tensor([[2.0, 0.0], [0.0, 2.0]]).repeat(2, 1)
>>> target = torch.tensor([0, 0, 1, 1])
>>> loss = OHEMLoss("CrossEntropyLoss", ohem_ratio=0.5)
>>> round(loss(logits, target).item(), 4)
2.1269
>>> loss = OHEMLoss(
...     "CrossEntropyLoss", ohem_ratio=0.5, ohem_threshold=0.9
... )
>>> round(loss(logits, target).item(), 4)
1.1269
```

Parameters

 * `predictions` (`Tensor`): The main output of the node, passed to the criterion. For the default criteria, logits of shape `[B,
   C, ...]`.
 * `target` (`Tensor`): The single label of the task, such as the `segmentation` label of shape `[B, C, H, W]`, passed to the
   criterion.

Returns

 * `Tensor`: The mean of the kept element losses, as a scalar. The value is `nan` when the method keeps no element. For an input
   without elements, the method returns the empty tensor of the element losses.

#### Attributes

##### criterion

##### supported_tasks
