| import torch |
| from torch import Tensor |
| from torch.nn import BCEWithLogitsLoss as TorchBCEWithLogitsLoss |
| from src.loss.weighted import WeightedLossMixIn |
|
|
|
|
| __all__ = ['WeightedBCEWithLogitsLoss', 'BCEWithLogitsLoss'] |
|
|
|
|
| class WeightedBCEWithLogitsLoss(WeightedLossMixIn, TorchBCEWithLogitsLoss): |
| """Weighted BCE loss between predicted and target offsets. This is |
| basically the BCEWithLogitsLoss except that positive weights must be |
| passed at forward time to give more importance to some items. |
| |
| Besides, we remove the constraint of passing `pos_weight` as a |
| Tensor. This simplifies instantiation with hydra. |
| """ |
|
|
| def __init__(self, *args, pos_weight=None, **kwargs): |
| if pos_weight is not None and not isinstance(pos_weight, Tensor): |
| pos_weight = torch.as_tensor(pos_weight) |
| super().__init__( |
| *args, pos_weight=pos_weight, reduction='none', **kwargs) |
|
|
| def load_state_dict(self, state_dict, strict=True): |
| """Normal `load_state_dict` behavior, except for the shared |
| `pos_weight`. |
| """ |
| |
| pos_weight = state_dict.get('pos_weight') |
| state_dict.pop('pos_weight') |
|
|
| |
| out = super().load_state_dict(state_dict, strict=strict) |
|
|
| |
| self.pos_weight = pos_weight |
|
|
| return out |
|
|
|
|
| class BCEWithLogitsLoss(WeightedBCEWithLogitsLoss): |
| """BCE loss between predicted and target offsets. |
| |
| The forward signature allows using this loss as a weighted loss, |
| with input weights ignored. |
| """ |
|
|
| def forward(self, input, target, weight): |
| return super().forward(input, target, None) |
|
|