losses¶
AdditiveAngularMarginLoss¶
- class AdditiveAngularMarginLoss(embedding_features, n_classes, scale=64.0, margin=0.5, **kwargs)¶
AKA ArcFaceLoss.
Reference
Deng et al. : ArcFace: Additive Angular Margin Loss for Deep Face Recognition
Note
this loss has weights and requires an optimizer.
margin
is already expressed in radians.
- Parameters
embedding_features (
int
) – number of embedding features inputs are expected to be (batch, embedding_features).n_classes (
int
) – number of classes in projection.scale (
float
) – Defaults to 64.0.margin (
float
) – margin in radians. Defaults to 0.5 (28.6 degrees).eps – epsilon for clamping . Defaults to 1e-7.
reduction – batch reduction for this loss should be one of ‘mean’, ‘sum’, ‘none’. Defaults to ‘mean’.
Example
>>> import torch >>> from hearth.losses import AdditiveAngularMarginLoss >>> _ = torch.manual_seed(666) >>> >>> >>> # this would be embeddings coming out of your model... >>> emb = torch.normal(0, 1, size=(5, 128)) >>> targets = torch.randint(0, 10, size=(5,)) >>> loss = AdditiveAngularMarginLoss(128, 10) >>> loss(emb, targets) tensor(41.8191, grad_fn=<MeanBackward0>)
BinaryFocalLoss¶
- class BinaryFocalLoss(alpha=0.25, gamma=2.0, mask_target_value=- 1, reduction='mean')¶
Binary focal loss.
Focal loss is a proposed solution for handling class imbalambce in segmentation.
Reference
Li et al. : Focal Loss for Dense Object Detection
- Parameters
alpha (
float
) – class weighting factor. Defaults to 0.25 (defaults taken from paper).gamma (
float
) – focusing factor. Defaults to 2.0 (default taken from paper).mask_target_value (
int
) – this index will be masked when seen in the targets upon computing the loss. Defaults to -1.reduction (
str
) – string name of reduction. Defaults to ‘mean’.
Shape
inputs: \((N, *)\) where \(*\) means, any number of additional dimensions if inputs have an extra single dimension thats ok… they will be reshaped as targets.
targets: \((N, *)\).
output: scalar unless
reduction
is'none'
, then \((N, *)\), same shape as targets.
Example
>>> import torch >>> from hearth.losses import BinaryFocalLoss >>> >>> targets = torch.tensor([0, 1, 0, 0, 1, 0], dtype=torch.float32) >>> inputs = torch.tensor([-1.1645, -0.2928, -0.5685, -0.8038, -0.0211, 2.0062]) >>> loss = BinaryFocalLoss() >>> loss BinaryFocalLoss(alpha=0.25, gamma=2.0, mask_target_value=-1, reduction='mean')
>>> loss(inputs, targets) tensor(0.2399)
if your inputs have an extra dim thats ok:
>>> loss(inputs.unsqueeze(-1), targets) tensor(0.2399)
supports masking by value for instance if we want to predict a binary value over time and the last timestep for the last example is missing, we can mask by setting
mask_target_value
to -1 and padding targets with -1:>>> masked_targets = torch.tensor([[0, 1, 0], [0, 1, -1]], dtype=torch.float32) >>> inputs = inputs.reshape((2, 3, -1)) # (batch, time, 1) >>> loss(inputs, masked_targets) tensor(0.0393)
when
reduction
is'none'
we will return one loss value per step as you can see the masked targets are 0.0:>>> loss = BinaryFocalLoss(reduction='none') >>> loss(inputs, masked_targets) tensor([[0.0115, 0.0697, 0.0440], [0.0265, 0.0449, 0.0000]])
- forward(inputs, targets)¶
Defines the computation performed at every call.
Should be overridden by all subclasses.
Note
Although the recipe for forward pass needs to be defined within this function, one should call the
Module
instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.- Return type
Tensor
- extra_repr()¶
Set the extra representation of the module
To print customized extra information, you should re-implement this method in your own modules. Both single-line and multi-line strings are acceptable.
- Return type
str
LargeMarginCosineLoss¶
- class LargeMarginCosineLoss(embedding_features, n_classes, scale=30.0, margin=0.4, **kwargs)¶
AKA CosFaceLoss.
Reference
Wang et al. : CosFace: Large Margin Cosine Loss for Deep Face Recognition
Note
this loss has weights and requires an optimizer.
- Parameters
embedding_features (
int
) – number of embedding features inputs are expected to be (batch, embedding_features).n_classes (
int
) – number of classes in projection.scale (
float
) – Defaults to 30.0.margin (
float
) – Defaults to 0.4.eps – epsilon for clamping . Defaults to 1e-7.
reduction – batch reduction for this loss should be one of ‘mean’, ‘sum’, ‘none’. Defaults to ‘mean’.
Example
>>> import torch >>> from hearth.losses import LargeMarginCosineLoss >>> _ = torch.manual_seed(666) >>> >>> >>> # this would be embeddings coming out of your model... >>> emb = torch.normal(0, 1, size=(5, 128)) >>> targets = torch.randint(0, 10, size=(5,)) >>> loss = LargeMarginCosineLoss(128, 10) >>> loss(emb, targets) tensor(17.5245, grad_fn=<MeanBackward0>)
MaskedMSELoss¶
- class MaskedMSELoss(mask_target_value=- inf, reduction='mean')¶
MSELoss with support for masked targets.
- Parameters
mask_target_value – ignore targets with this value. Defaults to -inf.
reduction (
str
) – Defaults to ‘mean’.
Example
>>> import torch >>> _ = torch.manual_seed(0) >>> from hearth.losses import MaskedMSELoss >>> >>> ninf = -float('inf') >>> loss = MaskedMSELoss() >>> inputs = torch.rand(3, 5) # (batch, timesteps) >>> targets = torch.tensor([[ 1.1721, 0.3909, -5.2731, ninf, ninf], ... [ 2.4388, 2.5159, -1.0815, -1.9472, -0.5450], ... [ 4.0665, -2.5141, ninf, ninf, ninf]]) >>> loss(inputs, targets) tensor(7.0101)
- forward(input, target)¶
Defines the computation performed at every call.
Should be overridden by all subclasses.
Note
Although the recipe for forward pass needs to be defined within this function, one should call the
Module
instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.- Return type
Tensor
- reduction: str¶
MultiHeadLoss¶
- class MultiHeadLoss(*, weights=None, aggregate_key='weighted_sum', **kwargs)¶
wrapper for losses for models with multiple output heads.
- Parameters
weights (
Union
[NumberDict
,Dict
[str
,int
],None
]) – a mapping of key to scalar weight, will be multiplied with losses before summing to create the aggregate value at aggregate_key, need not sum to 1. Defaults to None (all losses weighted evenly).aggregate_key (
str
) – the key to use for the aggregate loss. Defaults to ‘weighted_sum’.
Example
>>> import torch >>> from torch import nn >>> from hearth.losses import MultiHeadLoss >>> >>> _ =torch.manual_seed(0) >>> >>> loss = MultiHeadLoss(a=nn.BCEWithLogitsLoss(), ... b=nn.CrossEntropyLoss()) >>> loss MultiHeadLoss(a=BCEWithLogitsLoss(), b=CrossEntropyLoss(), weights=NumberDict({'a': 1.0, 'b': 1.0}), aggregate_key=weighted_sum)
multihead loss expects inputs and targets to be dicts with containing the it’s keys (in this case ‘a’ and ‘b’):
>>> batch_size = 10 >>> inputs = {'a': torch.rand(batch_size, 1), ... 'b': torch.normal(batch_size, 1, size=(batch_size, 4))} >>> targets = {'a': torch.rand(batch_size, 1).round(), ... 'b': torch.randint(4, size=(batch_size,))} >>> >>> loss(inputs, targets) TensorDict({'a': tensor(0.5791), 'b': tensor(1.2425), 'weighted_sum': tensor(1.8216)})
weighted_sum
is the default aggregate key. this is the bit you should call backward on. you can change the default aggregate key if you like by specifying it at init.>>> loss = MultiHeadLoss(a=nn.BCEWithLogitsLoss(), ... b=nn.CrossEntropyLoss(), ... aggregate_key='sally') >>> loss(inputs, targets) TensorDict({'a': tensor(0.5791), 'b': tensor(1.2425), 'sally': tensor(1.8216)})
you can aslo specify
weights
at init to weight contribution losses differently:>>> loss = MultiHeadLoss(a=nn.BCEWithLogitsLoss(), ... b=nn.CrossEntropyLoss(), ... weights={'a': .2, 'b':.8}) >>> loss(inputs, targets) TensorDict({'a': tensor(0.5791), 'b': tensor(1.2425), 'weighted_sum': tensor(1.1098)})
- property weights¶
- forward(inputs, targets, **kwargs)¶
Defines the computation performed at every call.
Should be overridden by all subclasses.
Note
Although the recipe for forward pass needs to be defined within this function, one should call the
Module
instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.- Return type
- training: bool¶
MulticlassFocalLoss¶
- class MulticlassFocalLoss(alpha=None, gamma=2.0, mask_target_value=- 1, reduction='mean')¶
multiclass focal loss.
Focal loss is a proposed solution for handling class imbalambce in segmentation.
Reference
Li et al. : Focal Loss for Dense Object Detection
- Parameters
alpha (
Union
[Tensor
,float
,None
]) – class weighting factor, may be a scalar, or a tensor with one weight per class if None alpha=1.0. Defaults to None.gamma (
float
) – focusing factor. Defaults to 2.0.mask_target_value (
int
) – this index will be masked when seen in the targets upon computing the loss. Defaults to -1.reduction (
str
) – string . Defaults to ‘mean’.
Shape
inputs: \((N, *)\) where \(*\) means, any number of additional dimensions
targets: \((N, *, C)\), where C = number of classes.
output: scalar unless
reduction
is'none'
, then \((N, *)\), same shape as targets.
Example
>>> import torch >>> from hearth.losses import MulticlassFocalLoss >>> >>> inp = torch.tensor([[ 1.3053, -0.6421, -1.2027, 1.0494, -1.9540], ... [ 0.6801, 0.2266, 0.8120, 0.9490, -0.8120], ... [-0.8212, 0.8024, 0.8370, -0.3272, 0.6125], ... [-0.1975, -1.0706, 2.6819, -0.4297, 0.1980], ... [ 0.8256, 1.7839, -1.5876, 1.7705, -1.7051], ... [ 0.1288, 1.0981, 0.0570, -1.1684, 0.4567], ... [ 0.5658, 1.3948, -1.1457, -0.5921, -0.8026], ... [-0.3989, 0.6574, 0.3411, -1.9814, 0.2935]]) >>> >>> targets = torch.tensor([0, 1, 4, 2, 3, 0, 2, 2]) >>> loss = MulticlassFocalLoss() >>> loss MulticlassFocalLoss(alpha=1.0, gamma=2.0, mask_target_value=-1, reduction='mean')
>>> loss(inp, targets) tensor(0.9478)
pass class weights for the alpha value:
>>> weights = torch.tensor([1.0, 2.0, 0.3, 2.1, .5]) >>> loss = MulticlassFocalLoss(alpha=weights) >>> loss(inp, targets) tensor(0.8010)
supports masking by value for instance if we want to predict classes over time and the last two timesteps for the last batch are missing we can mask them by setting to
mask_target_value
to -1 and padding targets with -1:>>> masked_targets = torch.tensor([[0, 1, 4, 2], [3, 0, -1, -1]]) # (batch, time) >>> inp = inp.reshape((2, 4, -1)) # (batch, time, classes) >>> loss(inp, masked_targets) tensor(0.8885)
when
reduction
is'none'
we will return one loss value per step as you can see the masked targets are 0.0:>>> loss = MulticlassFocalLoss(alpha=weights, reduction='none') >>> loss(inp, masked_targets) tensor([[1.8430e-01, 2.7830e+00, 4.0199e-01, 1.6719e-03], [6.7119e-01, 1.2889e+00, 0.0, 0.0]])
- property alpha¶
- forward(inputs, targets)¶
Defines the computation performed at every call.
Should be overridden by all subclasses.
Note
Although the recipe for forward pass needs to be defined within this function, one should call the
Module
instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.- Return type
Tensor
- extra_repr()¶
Set the extra representation of the module
To print customized extra information, you should re-implement this method in your own modules. Both single-line and multi-line strings are acceptable.
- Return type
str
SphereEmbeddingLoss¶
- class SphereEmbeddingLoss(embedding_features, n_classes, scale=64.0, margin=1.35, **kwargs)¶
AKA SphereFaceLoss.
Reference
Liu et al. : SphereFace: Deep Hypersphere Embedding for Face Recognition
Note
this loss has weights and requires an optimizer.
- Parameters
embedding_features (
int
) – number of embedding features inputs are expected to be (batch, embedding_features).n_classes (
int
) – number of classes in projection.scale (
float
) – Defaults to 64.0.margin (
float
) – Defaults to 1.35.eps – epsilon for clamping . Defaults to 1e-7.
reduction – batch reduction for this loss should be one of ‘mean’, ‘sum’, ‘none’. Defaults to ‘mean’.
Example
>>> import torch >>> from hearth.losses import SphereEmbeddingLoss >>> _ = torch.manual_seed(666) >>> >>> >>> # this would be embeddings coming out of your model... >>> emb = torch.normal(0, 1, size=(5, 128)) >>> targets = torch.randint(0, 10, size=(5,)) >>> loss = SphereEmbeddingLoss(128, 10) >>> loss(emb, targets) tensor(44.7385, grad_fn=<MeanBackward0>)