File size: 1,118 Bytes
b8fae22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
"""Loss builder. Everything is treated as MULTICLASS (binary == 2 classes),
which sidesteps the binary/multiclass mode pitfall and unifies all datasets.

  ce_dice : CrossEntropy + multiclass Dice  (default, robust for medical seg)
  ce      : CrossEntropy only
  dice    : multiclass Dice only

Inputs: logits [B,C,H,W], target [B,H,W] (long, ids 0..C-1).
"""
from __future__ import annotations

import torch
import torch.nn as nn
import segmentation_models_pytorch as smp


class CEDiceLoss(nn.Module):
    def __init__(self, mode: str = "ce_dice"):
        super().__init__()
        self.mode = mode
        self.ce = nn.CrossEntropyLoss()
        self.dice = smp.losses.DiceLoss(mode=smp.losses.MULTICLASS_MODE, from_logits=True)

    def forward(self, logits: torch.Tensor, target: torch.Tensor) -> torch.Tensor:
        if self.mode == "ce":
            return self.ce(logits, target)
        if self.mode == "dice":
            return self.dice(logits, target)
        return self.ce(logits, target) + self.dice(logits, target)


def build_loss(name: str = "ce_dice") -> nn.Module:
    return CEDiceLoss(name)