We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Extend loss weight calculation for classification
**Is your feature request related to a problem? Please describe.**
Currently, classification problems don't use weight calculations for specific classes. 

**Describe the solution you'd like**
Similar to segmentation, the weights should be dynamic.

**Describe alternatives you've considered**
N.A.

**Additional context**
N.A.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `GANDLF/losses.py`
Content:
```
1 import torch
2 import sys
3 from torch.nn import MSELoss, CrossEntropyLoss, L1Loss
4 from .utils import one_hot
5 
6 
7 # Dice scores and dice losses
8 def dice(inp, target):
9     smooth = 1e-7
10     iflat = inp.contiguous().view(-1)
11     tflat = target.contiguous().view(-1)
12     intersection = (iflat * tflat).sum()
13     # 2 * intersection / union
14     return (2.0 * intersection + smooth) / (iflat.sum() + tflat.sum() + smooth)
15 
16 
17 def cel(out, target, params):
18     if len(target.shape) > 1 and target.shape[-1] == 1:
19         target = torch.squeeze(target, -1)
20 
21     class_weights = None
22     if params["class_weights"]:
23         class_weights = torch.FloatTensor(list(params["class_weights"].values()))
24 
25         # more examples you have in the training data, the smaller the weight you have in the loss
26         class_weights = 1.0 / class_weights
27 
28         class_weights = class_weights.float().to(params["device"])
29 
30     cel = CrossEntropyLoss(weight=class_weights)
31     return cel(out, target)
32 
33 
34 def MCD(pm, gt, num_class, weights=None, ignore_class=None, loss_type=0):
35     """
36     These weights should be the dice weights, not dice weights
37     loss_type:
38         0: no loss, normal dice calculation
39         1: dice loss, (1-dice)
40         2: log dice, -log(dice)
41     """
42     acc_dice = 0
43     for i in range(0, num_class):  # 0 is background
44         calculate_dice_for_label = True
45         if ignore_class is not None:
46             if i == ignore_class:
47                 calculate_dice_for_label = False
48 
49         if calculate_dice_for_label:
50             currentDice = dice(gt[:, i, ...], pm[:, i, ...])
51             if loss_type == 1:
52                 currentDice = 1 - currentDice  # subtract from 1 because this is a loss
53             elif loss_type == 2:
54                 # negative because we want positive losses
55                 currentDice = -torch.log(currentDice + torch.finfo(torch.float32).eps)
56             if weights is not None:
57                 currentDice = currentDice * weights[i]
58             acc_dice += currentDice
59     if weights is None:
60         acc_dice /= num_class  # we should not be considering 0
61     return acc_dice
62 
63 
64 def MCD_loss(pm, gt, params):
65     """
66     These weights should be the penalty weights, not dice weights
67     """
68     gt = one_hot(gt, params["model"]["class_list"])
69     return MCD(pm, gt, len(params["model"]["class_list"]), params["weights"], None, 1)
70 
71 
72 def MCD_loss_new(pm, gt, num_class, weights=None):  # compute the actual dice score
73     dims = (1, 2, 3)
74     eps = torch.finfo(torch.float32).eps
75     intersection = torch.sum(pm * gt, dims)
76     cardinality = torch.sum(pm + gt, dims)
77 
78     dice_score = (2.0 * intersection + eps) / (cardinality + eps)
79 
80     return torch.mean(-dice_score + 1.0)
81 
82 
83 def MCD_log_loss(pm, gt, params):
84     """
85     These weights should be the penalty weights, not dice weights
86     """
87     gt = one_hot(gt, params["model"]["class_list"])
88     return MCD(pm, gt, len(params["model"]["class_list"]), params["weights"], None, 2)
89 
90 
91 def CE_Logits(out, target):
92     iflat = out.contiguous().view(-1)
93     tflat = target.contiguous().view(-1)
94     loss = torch.nn.BCEWithLogitsLoss()
95     loss_val = loss(iflat, tflat)
96     return loss_val
97 
98 
99 def CE(out, target):
100     iflat = out.contiguous().view(-1)
101     tflat = target.contiguous().view(-1)
102     loss = torch.nn.BCELoss()
103     loss_val = loss(iflat, tflat)
104     return loss_val
105 
106 
107 def CCE_Generic(out, target, params, CCE_Type):
108     """
109     Generic function to calculate CCE loss
110 
111     Args:
112         out (torch.tensor): The predicted output value for each pixel. dimension: [batch, class, x, y, z].
113         target (torch.tensor): The ground truth label for each pixel. dimension: [batch, class, x, y, z] factorial_class_list.
114         params (dict): The parameter dictionary.
115         CCE_Type (torch.nn): The CE loss function type.
116 
117     Returns:
118         torch.tensor: The final loss value after taking multiple classes into consideration
119     """
120 
121     acc_ce_loss = 0
122     target = one_hot(target, params["model"]["class_list"]).type(out.dtype)
123     for i in range(0, len(params["model"]["class_list"])):
124         curr_ce_loss = CCE_Type(out[:, i, ...], target[:, i, ...])
125         if params["weights"] is not None:
126             curr_ce_loss = curr_ce_loss * params["weights"][i]
127         acc_ce_loss += curr_ce_loss
128     if params["weights"] is None:
129         acc_ce_loss /= len(params["model"]["class_list"])
130     return acc_ce_loss
131 
132 
133 def DCCE(pm, gt, params):
134     dcce_loss = MCD_loss(pm, gt, params) + CCE_Generic(pm, gt, params, CE)
135     return dcce_loss
136 
137 
138 def DCCE_Logits(pm, gt, params):
139     dcce_loss = MCD_loss(pm, gt, params) + CCE_Generic(pm, gt, params, CE_Logits)
140     return dcce_loss
141 
142 
143 def tversky(inp, target, alpha):
144     smooth = 1e-7
145     iflat = inp.view(-1)
146     tflat = target.view(-1)
147     intersection = (iflat * tflat).sum()
148     fps = (iflat * (1 - tflat)).sum()
149     fns = ((1 - iflat) * tflat).sum()
150     denominator = intersection + (alpha * fps) + ((1 - alpha) * fns) + smooth
151     return (intersection + smooth) / denominator
152 
153 
154 def tversky_loss(inp, target, alpha=1):
155     tversky_val = tversky(inp, target, alpha)
156     return 1 - tversky_val
157 
158 
159 def MCT_loss(inp, target, num_class, weights):
160     acc_tv_loss = 0
161     for i in range(0, num_class):
162         acc_tv_loss += tversky_loss(inp[:, i, ...], target[:, i, ...]) * weights[i]
163     acc_tv_loss /= num_class - 1
164     return acc_tv_loss
165 
166 
167 def KullbackLeiblerDivergence(mu, logvar, params=None):
168     loss = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp(), dim=-1)
169     return loss.mean()
170 
171 
172 def L1(output, label, reduction="mean", scaling_factor=1):
173     """
174     Calculate the mean square error between the output variable from the network and the target
175 
176     Parameters
177     ----------
178     output : torch.Tensor
179         The output generated usually by the network
180     target : torch.Tensor
181         The label for the corresponding Tensor for which the output was generated
182     reduction : string, optional
183         DESCRIPTION. The default is 'mean'.
184     scaling_factor : integer, optional
185         The scaling factor to multiply the label with
186 
187     Returns
188     -------
189     loss : torch.Tensor
190         Computed Mean Squared Error loss for the output and label
191 
192     """
193     scaling_factor = torch.as_tensor(scaling_factor)
194     label = label.float()
195     label = label * scaling_factor
196     loss_fn = L1Loss(reduction=reduction)
197     iflat = output.contiguous().view(-1)
198     tflat = label.contiguous().view(-1)
199     loss = loss_fn(iflat, tflat)
200     return loss
201 
202 
203 def L1_loss(inp, target, params):
204     acc_mse_loss = 0
205     # if inp.shape != target.shape:
206     #     sys.exit('Input and target shapes are inconsistent')
207 
208     if inp.shape[0] == 1:
209         if params is not None:
210             acc_mse_loss += L1(
211                 inp,
212                 target,
213                 reduction=params["loss_function"]["l1"]["reduction"],
214                 scaling_factor=params["scaling_factor"],
215             )
216         else:
217             acc_mse_loss += L1(inp, target)
218         # for i in range(0, params["model"]["num_classes"]):
219         #    acc_mse_loss += MSE(inp[i], target[i], reduction=params["loss_function"]['mse']["reduction"])
220     else:
221         if params is not None:
222             for i in range(0, params["model"]["num_classes"]):
223                 acc_mse_loss += L1(
224                     inp[:, i, ...],
225                     target[:, i, ...],
226                     reduction=params["loss_function"]["mse"]["reduction"],
227                     scaling_factor=params["scaling_factor"],
228                 )
229         else:
230             for i in range(0, inp.shape[1]):
231                 acc_mse_loss += L1(inp[:, i, ...], target[:, i, ...])
232     if params is not None:
233         acc_mse_loss /= params["model"]["num_classes"]
234     else:
235         acc_mse_loss /= inp.shape[1]
236 
237     return acc_mse_loss
238 
239 
240 def MSE(output, label, reduction="mean", scaling_factor=1):
241     """
242     Calculate the mean square error between the output variable from the network and the target
243 
244     Parameters
245     ----------
246     output : torch.Tensor
247         The output generated usually by the network
248     target : torch.Tensor
249         The label for the corresponding Tensor for which the output was generated
250     reduction : string, optional
251         DESCRIPTION. The default is 'mean'.
252     scaling_factor : integer, optional
253         The scaling factor to multiply the label with
254 
255     Returns
256     -------
257     loss : torch.Tensor
258         Computed Mean Squared Error loss for the output and label
259 
260     """
261     scaling_factor = torch.as_tensor(scaling_factor)
262     label = label.float()
263     label = label * scaling_factor
264     loss_fn = MSELoss(reduction=reduction)
265     iflat = output.contiguous().view(-1)
266     tflat = label.contiguous().view(-1)
267     loss = loss_fn(iflat, tflat)
268     return loss
269 
270 
271 def MSE_loss(inp, target, params):
272     acc_mse_loss = 0
273     # if inp.shape != target.shape:
274     #     sys.exit('Input and target shapes are inconsistent')
275 
276     if inp.shape[0] == 1:
277         if params is not None:
278             acc_mse_loss += MSE(
279                 inp,
280                 target,
281                 reduction=params["loss_function"]["mse"]["reduction"],
282                 scaling_factor=params["scaling_factor"],
283             )
284         else:
285             acc_mse_loss += MSE(inp, target)
286         # for i in range(0, params["model"]["num_classes"]):
287         #    acc_mse_loss += MSE(inp[i], target[i], reduction=params["loss_function"]['mse']["reduction"])
288     else:
289         if params is not None:
290             for i in range(0, params["model"]["num_classes"]):
291                 acc_mse_loss += MSE(
292                     inp[:, i, ...],
293                     target[:, i, ...],
294                     reduction=params["loss_function"]["mse"]["reduction"],
295                     scaling_factor=params["scaling_factor"],
296                 )
297         else:
298             for i in range(0, inp.shape[1]):
299                 acc_mse_loss += MSE(inp[:, i, ...], target[:, i, ...])
300     if params is not None:
301         acc_mse_loss /= params["model"]["num_classes"]
302     else:
303         acc_mse_loss /= inp.shape[1]
304 
305     return acc_mse_loss
306 
307 
308 def fetch_loss_function(loss_name, params):
309 
310     if isinstance(loss_name, dict):  # this is currently only happening for mse_torch
311         # check for mse_torch
312         loss_function = MSE_loss
313     elif loss_name == "dc":
314         loss_function = MCD_loss
315     elif loss_name == "dc_log":
316         loss_function = MCD_log_loss
317     elif loss_name == "dcce":
318         loss_function = DCCE
319     elif loss_name == "dcce_logits":
320         loss_function = DCCE_Logits
321     elif loss_name == "ce":
322         loss_function = CE
323     elif loss_name == "mse":
324         loss_function = MSE_loss
325     elif loss_name == "cel":
326         loss_function = cel
327     elif loss_name == "kld":
328         loss_function = KullbackLeiblerDivergence
329     elif loss_name == "l1":
330         loss_function = L1_loss
331     else:
332         print(
333             "WARNING: Could not find the requested loss function '"
334             + loss_name
335             + "' in the implementation, using dc, instead",
336             file=sys.stderr,
337         )
338         loss_name = "dc"
339         loss_function = MCD_loss
340     return loss_function
341
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/GANDLF/losses.py b/GANDLF/losses.py
--- a/GANDLF/losses.py
+++ b/GANDLF/losses.py
@@ -25,8 +25,8 @@
         # more examples you have in the training data, the smaller the weight you have in the loss
         class_weights = 1.0 / class_weights
 
-        class_weights = class_weights.float().to(params["device"])
-
+        class_weights = class_weights.float().to(target.device)
+        
     cel = CrossEntropyLoss(weight=class_weights)
     return cel(out, target)

{"golden_diff": "diff --git a/GANDLF/losses.py b/GANDLF/losses.py\n--- a/GANDLF/losses.py\n+++ b/GANDLF/losses.py\n@@ -25,8 +25,8 @@\n         # more examples you have in the training data, the smaller the weight you have in the loss\n         class_weights = 1.0 / class_weights\n \n-        class_weights = class_weights.float().to(params[\"device\"])\n-\n+        class_weights = class_weights.float().to(target.device)\n+        \n     cel = CrossEntropyLoss(weight=class_weights)\n     return cel(out, target)\n", "issue": "Extend loss weight calculation for classification\n**Is your feature request related to a problem? Please describe.**\r\nCurrently, classification problems don't use weight calculations for specific classes. \r\n\r\n**Describe the solution you'd like**\r\nSimilar to segmentation, the weights should be dynamic.\r\n\r\n**Describe alternatives you've considered**\r\nN.A.\r\n\r\n**Additional context**\r\nN.A.\r\n\n", "before_files": [{"content": "import torch\nimport sys\nfrom torch.nn import MSELoss, CrossEntropyLoss, L1Loss\nfrom .utils import one_hot\n\n\n# Dice scores and dice losses\ndef dice(inp, target):\n    smooth = 1e-7\n    iflat = inp.contiguous().view(-1)\n    tflat = target.contiguous().view(-1)\n    intersection = (iflat * tflat).sum()\n    # 2 * intersection / union\n    return (2.0 * intersection + smooth) / (iflat.sum() + tflat.sum() + smooth)\n\n\ndef cel(out, target, params):\n    if len(target.shape) > 1 and target.shape[-1] == 1:\n        target = torch.squeeze(target, -1)\n\n    class_weights = None\n    if params[\"class_weights\"]:\n        class_weights = torch.FloatTensor(list(params[\"class_weights\"].values()))\n\n        # more examples you have in the training data, the smaller the weight you have in the loss\n        class_weights = 1.0 / class_weights\n\n        class_weights = class_weights.float().to(params[\"device\"])\n\n    cel = CrossEntropyLoss(weight=class_weights)\n    return cel(out, target)\n\n\ndef MCD(pm, gt, num_class, weights=None, ignore_class=None, loss_type=0):\n    \"\"\"\n    These weights should be the dice weights, not dice weights\n    loss_type:\n        0: no loss, normal dice calculation\n        1: dice loss, (1-dice)\n        2: log dice, -log(dice)\n    \"\"\"\n    acc_dice = 0\n    for i in range(0, num_class):  # 0 is background\n        calculate_dice_for_label = True\n        if ignore_class is not None:\n            if i == ignore_class:\n                calculate_dice_for_label = False\n\n        if calculate_dice_for_label:\n            currentDice = dice(gt[:, i, ...], pm[:, i, ...])\n            if loss_type == 1:\n                currentDice = 1 - currentDice  # subtract from 1 because this is a loss\n            elif loss_type == 2:\n                # negative because we want positive losses\n                currentDice = -torch.log(currentDice + torch.finfo(torch.float32).eps)\n            if weights is not None:\n                currentDice = currentDice * weights[i]\n            acc_dice += currentDice\n    if weights is None:\n        acc_dice /= num_class  # we should not be considering 0\n    return acc_dice\n\n\ndef MCD_loss(pm, gt, params):\n    \"\"\"\n    These weights should be the penalty weights, not dice weights\n    \"\"\"\n    gt = one_hot(gt, params[\"model\"][\"class_list\"])\n    return MCD(pm, gt, len(params[\"model\"][\"class_list\"]), params[\"weights\"], None, 1)\n\n\ndef MCD_loss_new(pm, gt, num_class, weights=None):  # compute the actual dice score\n    dims = (1, 2, 3)\n    eps = torch.finfo(torch.float32).eps\n    intersection = torch.sum(pm * gt, dims)\n    cardinality = torch.sum(pm + gt, dims)\n\n    dice_score = (2.0 * intersection + eps) / (cardinality + eps)\n\n    return torch.mean(-dice_score + 1.0)\n\n\ndef MCD_log_loss(pm, gt, params):\n    \"\"\"\n    These weights should be the penalty weights, not dice weights\n    \"\"\"\n    gt = one_hot(gt, params[\"model\"][\"class_list\"])\n    return MCD(pm, gt, len(params[\"model\"][\"class_list\"]), params[\"weights\"], None, 2)\n\n\ndef CE_Logits(out, target):\n    iflat = out.contiguous().view(-1)\n    tflat = target.contiguous().view(-1)\n    loss = torch.nn.BCEWithLogitsLoss()\n    loss_val = loss(iflat, tflat)\n    return loss_val\n\n\ndef CE(out, target):\n    iflat = out.contiguous().view(-1)\n    tflat = target.contiguous().view(-1)\n    loss = torch.nn.BCELoss()\n    loss_val = loss(iflat, tflat)\n    return loss_val\n\n\ndef CCE_Generic(out, target, params, CCE_Type):\n    \"\"\"\n    Generic function to calculate CCE loss\n\n    Args:\n        out (torch.tensor): The predicted output value for each pixel. dimension: [batch, class, x, y, z].\n        target (torch.tensor): The ground truth label for each pixel. dimension: [batch, class, x, y, z] factorial_class_list.\n        params (dict): The parameter dictionary.\n        CCE_Type (torch.nn): The CE loss function type.\n\n    Returns:\n        torch.tensor: The final loss value after taking multiple classes into consideration\n    \"\"\"\n\n    acc_ce_loss = 0\n    target = one_hot(target, params[\"model\"][\"class_list\"]).type(out.dtype)\n    for i in range(0, len(params[\"model\"][\"class_list\"])):\n        curr_ce_loss = CCE_Type(out[:, i, ...], target[:, i, ...])\n        if params[\"weights\"] is not None:\n            curr_ce_loss = curr_ce_loss * params[\"weights\"][i]\n        acc_ce_loss += curr_ce_loss\n    if params[\"weights\"] is None:\n        acc_ce_loss /= len(params[\"model\"][\"class_list\"])\n    return acc_ce_loss\n\n\ndef DCCE(pm, gt, params):\n    dcce_loss = MCD_loss(pm, gt, params) + CCE_Generic(pm, gt, params, CE)\n    return dcce_loss\n\n\ndef DCCE_Logits(pm, gt, params):\n    dcce_loss = MCD_loss(pm, gt, params) + CCE_Generic(pm, gt, params, CE_Logits)\n    return dcce_loss\n\n\ndef tversky(inp, target, alpha):\n    smooth = 1e-7\n    iflat = inp.view(-1)\n    tflat = target.view(-1)\n    intersection = (iflat * tflat).sum()\n    fps = (iflat * (1 - tflat)).sum()\n    fns = ((1 - iflat) * tflat).sum()\n    denominator = intersection + (alpha * fps) + ((1 - alpha) * fns) + smooth\n    return (intersection + smooth) / denominator\n\n\ndef tversky_loss(inp, target, alpha=1):\n    tversky_val = tversky(inp, target, alpha)\n    return 1 - tversky_val\n\n\ndef MCT_loss(inp, target, num_class, weights):\n    acc_tv_loss = 0\n    for i in range(0, num_class):\n        acc_tv_loss += tversky_loss(inp[:, i, ...], target[:, i, ...]) * weights[i]\n    acc_tv_loss /= num_class - 1\n    return acc_tv_loss\n\n\ndef KullbackLeiblerDivergence(mu, logvar, params=None):\n    loss = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp(), dim=-1)\n    return loss.mean()\n\n\ndef L1(output, label, reduction=\"mean\", scaling_factor=1):\n    \"\"\"\n    Calculate the mean square error between the output variable from the network and the target\n\n    Parameters\n    ----------\n    output : torch.Tensor\n        The output generated usually by the network\n    target : torch.Tensor\n        The label for the corresponding Tensor for which the output was generated\n    reduction : string, optional\n        DESCRIPTION. The default is 'mean'.\n    scaling_factor : integer, optional\n        The scaling factor to multiply the label with\n\n    Returns\n    -------\n    loss : torch.Tensor\n        Computed Mean Squared Error loss for the output and label\n\n    \"\"\"\n    scaling_factor = torch.as_tensor(scaling_factor)\n    label = label.float()\n    label = label * scaling_factor\n    loss_fn = L1Loss(reduction=reduction)\n    iflat = output.contiguous().view(-1)\n    tflat = label.contiguous().view(-1)\n    loss = loss_fn(iflat, tflat)\n    return loss\n\n\ndef L1_loss(inp, target, params):\n    acc_mse_loss = 0\n    # if inp.shape != target.shape:\n    #     sys.exit('Input and target shapes are inconsistent')\n\n    if inp.shape[0] == 1:\n        if params is not None:\n            acc_mse_loss += L1(\n                inp,\n                target,\n                reduction=params[\"loss_function\"][\"l1\"][\"reduction\"],\n                scaling_factor=params[\"scaling_factor\"],\n            )\n        else:\n            acc_mse_loss += L1(inp, target)\n        # for i in range(0, params[\"model\"][\"num_classes\"]):\n        #    acc_mse_loss += MSE(inp[i], target[i], reduction=params[\"loss_function\"]['mse'][\"reduction\"])\n    else:\n        if params is not None:\n            for i in range(0, params[\"model\"][\"num_classes\"]):\n                acc_mse_loss += L1(\n                    inp[:, i, ...],\n                    target[:, i, ...],\n                    reduction=params[\"loss_function\"][\"mse\"][\"reduction\"],\n                    scaling_factor=params[\"scaling_factor\"],\n                )\n        else:\n            for i in range(0, inp.shape[1]):\n                acc_mse_loss += L1(inp[:, i, ...], target[:, i, ...])\n    if params is not None:\n        acc_mse_loss /= params[\"model\"][\"num_classes\"]\n    else:\n        acc_mse_loss /= inp.shape[1]\n\n    return acc_mse_loss\n\n\ndef MSE(output, label, reduction=\"mean\", scaling_factor=1):\n    \"\"\"\n    Calculate the mean square error between the output variable from the network and the target\n\n    Parameters\n    ----------\n    output : torch.Tensor\n        The output generated usually by the network\n    target : torch.Tensor\n        The label for the corresponding Tensor for which the output was generated\n    reduction : string, optional\n        DESCRIPTION. The default is 'mean'.\n    scaling_factor : integer, optional\n        The scaling factor to multiply the label with\n\n    Returns\n    -------\n    loss : torch.Tensor\n        Computed Mean Squared Error loss for the output and label\n\n    \"\"\"\n    scaling_factor = torch.as_tensor(scaling_factor)\n    label = label.float()\n    label = label * scaling_factor\n    loss_fn = MSELoss(reduction=reduction)\n    iflat = output.contiguous().view(-1)\n    tflat = label.contiguous().view(-1)\n    loss = loss_fn(iflat, tflat)\n    return loss\n\n\ndef MSE_loss(inp, target, params):\n    acc_mse_loss = 0\n    # if inp.shape != target.shape:\n    #     sys.exit('Input and target shapes are inconsistent')\n\n    if inp.shape[0] == 1:\n        if params is not None:\n            acc_mse_loss += MSE(\n                inp,\n                target,\n                reduction=params[\"loss_function\"][\"mse\"][\"reduction\"],\n                scaling_factor=params[\"scaling_factor\"],\n            )\n        else:\n            acc_mse_loss += MSE(inp, target)\n        # for i in range(0, params[\"model\"][\"num_classes\"]):\n        #    acc_mse_loss += MSE(inp[i], target[i], reduction=params[\"loss_function\"]['mse'][\"reduction\"])\n    else:\n        if params is not None:\n            for i in range(0, params[\"model\"][\"num_classes\"]):\n                acc_mse_loss += MSE(\n                    inp[:, i, ...],\n                    target[:, i, ...],\n                    reduction=params[\"loss_function\"][\"mse\"][\"reduction\"],\n                    scaling_factor=params[\"scaling_factor\"],\n                )\n        else:\n            for i in range(0, inp.shape[1]):\n                acc_mse_loss += MSE(inp[:, i, ...], target[:, i, ...])\n    if params is not None:\n        acc_mse_loss /= params[\"model\"][\"num_classes\"]\n    else:\n        acc_mse_loss /= inp.shape[1]\n\n    return acc_mse_loss\n\n\ndef fetch_loss_function(loss_name, params):\n\n    if isinstance(loss_name, dict):  # this is currently only happening for mse_torch\n        # check for mse_torch\n        loss_function = MSE_loss\n    elif loss_name == \"dc\":\n        loss_function = MCD_loss\n    elif loss_name == \"dc_log\":\n        loss_function = MCD_log_loss\n    elif loss_name == \"dcce\":\n        loss_function = DCCE\n    elif loss_name == \"dcce_logits\":\n        loss_function = DCCE_Logits\n    elif loss_name == \"ce\":\n        loss_function = CE\n    elif loss_name == \"mse\":\n        loss_function = MSE_loss\n    elif loss_name == \"cel\":\n        loss_function = cel\n    elif loss_name == \"kld\":\n        loss_function = KullbackLeiblerDivergence\n    elif loss_name == \"l1\":\n        loss_function = L1_loss\n    else:\n        print(\n            \"WARNING: Could not find the requested loss function '\"\n            + loss_name\n            + \"' in the implementation, using dc, instead\",\n            file=sys.stderr,\n        )\n        loss_name = \"dc\"\n        loss_function = MCD_loss\n    return loss_function\n", "path": "GANDLF/losses.py"}], "after_files": [{"content": "import torch\nimport sys\nfrom torch.nn import MSELoss, CrossEntropyLoss, L1Loss\nfrom .utils import one_hot\n\n\n# Dice scores and dice losses\ndef dice(inp, target):\n    smooth = 1e-7\n    iflat = inp.contiguous().view(-1)\n    tflat = target.contiguous().view(-1)\n    intersection = (iflat * tflat).sum()\n    # 2 * intersection / union\n    return (2.0 * intersection + smooth) / (iflat.sum() + tflat.sum() + smooth)\n\n\ndef cel(out, target, params):\n    if len(target.shape) > 1 and target.shape[-1] == 1:\n        target = torch.squeeze(target, -1)\n\n    class_weights = None\n    if params[\"class_weights\"]:\n        class_weights = torch.FloatTensor(list(params[\"class_weights\"].values()))\n\n        # more examples you have in the training data, the smaller the weight you have in the loss\n        class_weights = 1.0 / class_weights\n\n        class_weights = class_weights.float().to(target.device)\n        \n    cel = CrossEntropyLoss(weight=class_weights)\n    return cel(out, target)\n\n\ndef MCD(pm, gt, num_class, weights=None, ignore_class=None, loss_type=0):\n    \"\"\"\n    These weights should be the dice weights, not dice weights\n    loss_type:\n        0: no loss, normal dice calculation\n        1: dice loss, (1-dice)\n        2: log dice, -log(dice)\n    \"\"\"\n    acc_dice = 0\n    for i in range(0, num_class):  # 0 is background\n        calculate_dice_for_label = True\n        if ignore_class is not None:\n            if i == ignore_class:\n                calculate_dice_for_label = False\n\n        if calculate_dice_for_label:\n            currentDice = dice(gt[:, i, ...], pm[:, i, ...])\n            if loss_type == 1:\n                currentDice = 1 - currentDice  # subtract from 1 because this is a loss\n            elif loss_type == 2:\n                # negative because we want positive losses\n                currentDice = -torch.log(currentDice + torch.finfo(torch.float32).eps)\n            if weights is not None:\n                currentDice = currentDice * weights[i]\n            acc_dice += currentDice\n    if weights is None:\n        acc_dice /= num_class  # we should not be considering 0\n    return acc_dice\n\n\ndef MCD_loss(pm, gt, params):\n    \"\"\"\n    These weights should be the penalty weights, not dice weights\n    \"\"\"\n    gt = one_hot(gt, params[\"model\"][\"class_list\"])\n    return MCD(pm, gt, len(params[\"model\"][\"class_list\"]), params[\"weights\"], None, 1)\n\n\ndef MCD_loss_new(pm, gt, num_class, weights=None):  # compute the actual dice score\n    dims = (1, 2, 3)\n    eps = torch.finfo(torch.float32).eps\n    intersection = torch.sum(pm * gt, dims)\n    cardinality = torch.sum(pm + gt, dims)\n\n    dice_score = (2.0 * intersection + eps) / (cardinality + eps)\n\n    return torch.mean(-dice_score + 1.0)\n\n\ndef MCD_log_loss(pm, gt, params):\n    \"\"\"\n    These weights should be the penalty weights, not dice weights\n    \"\"\"\n    gt = one_hot(gt, params[\"model\"][\"class_list\"])\n    return MCD(pm, gt, len(params[\"model\"][\"class_list\"]), params[\"weights\"], None, 2)\n\n\ndef CE_Logits(out, target):\n    iflat = out.contiguous().view(-1)\n    tflat = target.contiguous().view(-1)\n    loss = torch.nn.BCEWithLogitsLoss()\n    loss_val = loss(iflat, tflat)\n    return loss_val\n\n\ndef CE(out, target):\n    iflat = out.contiguous().view(-1)\n    tflat = target.contiguous().view(-1)\n    loss = torch.nn.BCELoss()\n    loss_val = loss(iflat, tflat)\n    return loss_val\n\n\ndef CCE_Generic(out, target, params, CCE_Type):\n    \"\"\"\n    Generic function to calculate CCE loss\n\n    Args:\n        out (torch.tensor): The predicted output value for each pixel. dimension: [batch, class, x, y, z].\n        target (torch.tensor): The ground truth label for each pixel. dimension: [batch, class, x, y, z] factorial_class_list.\n        params (dict): The parameter dictionary.\n        CCE_Type (torch.nn): The CE loss function type.\n\n    Returns:\n        torch.tensor: The final loss value after taking multiple classes into consideration\n    \"\"\"\n\n    acc_ce_loss = 0\n    target = one_hot(target, params[\"model\"][\"class_list\"]).type(out.dtype)\n    for i in range(0, len(params[\"model\"][\"class_list\"])):\n        curr_ce_loss = CCE_Type(out[:, i, ...], target[:, i, ...])\n        if params[\"weights\"] is not None:\n            curr_ce_loss = curr_ce_loss * params[\"weights\"][i]\n        acc_ce_loss += curr_ce_loss\n    if params[\"weights\"] is None:\n        acc_ce_loss /= len(params[\"model\"][\"class_list\"])\n    return acc_ce_loss\n\n\ndef DCCE(pm, gt, params):\n    dcce_loss = MCD_loss(pm, gt, params) + CCE_Generic(pm, gt, params, CE)\n    return dcce_loss\n\n\ndef DCCE_Logits(pm, gt, params):\n    dcce_loss = MCD_loss(pm, gt, params) + CCE_Generic(pm, gt, params, CE_Logits)\n    return dcce_loss\n\n\ndef tversky(inp, target, alpha):\n    smooth = 1e-7\n    iflat = inp.view(-1)\n    tflat = target.view(-1)\n    intersection = (iflat * tflat).sum()\n    fps = (iflat * (1 - tflat)).sum()\n    fns = ((1 - iflat) * tflat).sum()\n    denominator = intersection + (alpha * fps) + ((1 - alpha) * fns) + smooth\n    return (intersection + smooth) / denominator\n\n\ndef tversky_loss(inp, target, alpha=1):\n    tversky_val = tversky(inp, target, alpha)\n    return 1 - tversky_val\n\n\ndef MCT_loss(inp, target, num_class, weights):\n    acc_tv_loss = 0\n    for i in range(0, num_class):\n        acc_tv_loss += tversky_loss(inp[:, i, ...], target[:, i, ...]) * weights[i]\n    acc_tv_loss /= num_class - 1\n    return acc_tv_loss\n\n\ndef KullbackLeiblerDivergence(mu, logvar, params=None):\n    loss = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp(), dim=-1)\n    return loss.mean()\n\n\ndef L1(output, label, reduction=\"mean\", scaling_factor=1):\n    \"\"\"\n    Calculate the mean square error between the output variable from the network and the target\n\n    Parameters\n    ----------\n    output : torch.Tensor\n        The output generated usually by the network\n    target : torch.Tensor\n        The label for the corresponding Tensor for which the output was generated\n    reduction : string, optional\n        DESCRIPTION. The default is 'mean'.\n    scaling_factor : integer, optional\n        The scaling factor to multiply the label with\n\n    Returns\n    -------\n    loss : torch.Tensor\n        Computed Mean Squared Error loss for the output and label\n\n    \"\"\"\n    scaling_factor = torch.as_tensor(scaling_factor)\n    label = label.float()\n    label = label * scaling_factor\n    loss_fn = L1Loss(reduction=reduction)\n    iflat = output.contiguous().view(-1)\n    tflat = label.contiguous().view(-1)\n    loss = loss_fn(iflat, tflat)\n    return loss\n\n\ndef L1_loss(inp, target, params):\n    acc_mse_loss = 0\n    # if inp.shape != target.shape:\n    #     sys.exit('Input and target shapes are inconsistent')\n\n    if inp.shape[0] == 1:\n        if params is not None:\n            acc_mse_loss += L1(\n                inp,\n                target,\n                reduction=params[\"loss_function\"][\"l1\"][\"reduction\"],\n                scaling_factor=params[\"scaling_factor\"],\n            )\n        else:\n            acc_mse_loss += L1(inp, target)\n        # for i in range(0, params[\"model\"][\"num_classes\"]):\n        #    acc_mse_loss += MSE(inp[i], target[i], reduction=params[\"loss_function\"]['mse'][\"reduction\"])\n    else:\n        if params is not None:\n            for i in range(0, params[\"model\"][\"num_classes\"]):\n                acc_mse_loss += L1(\n                    inp[:, i, ...],\n                    target[:, i, ...],\n                    reduction=params[\"loss_function\"][\"mse\"][\"reduction\"],\n                    scaling_factor=params[\"scaling_factor\"],\n                )\n        else:\n            for i in range(0, inp.shape[1]):\n                acc_mse_loss += L1(inp[:, i, ...], target[:, i, ...])\n    if params is not None:\n        acc_mse_loss /= params[\"model\"][\"num_classes\"]\n    else:\n        acc_mse_loss /= inp.shape[1]\n\n    return acc_mse_loss\n\n\ndef MSE(output, label, reduction=\"mean\", scaling_factor=1):\n    \"\"\"\n    Calculate the mean square error between the output variable from the network and the target\n\n    Parameters\n    ----------\n    output : torch.Tensor\n        The output generated usually by the network\n    target : torch.Tensor\n        The label for the corresponding Tensor for which the output was generated\n    reduction : string, optional\n        DESCRIPTION. The default is 'mean'.\n    scaling_factor : integer, optional\n        The scaling factor to multiply the label with\n\n    Returns\n    -------\n    loss : torch.Tensor\n        Computed Mean Squared Error loss for the output and label\n\n    \"\"\"\n    scaling_factor = torch.as_tensor(scaling_factor)\n    label = label.float()\n    label = label * scaling_factor\n    loss_fn = MSELoss(reduction=reduction)\n    iflat = output.contiguous().view(-1)\n    tflat = label.contiguous().view(-1)\n    loss = loss_fn(iflat, tflat)\n    return loss\n\n\ndef MSE_loss(inp, target, params):\n    acc_mse_loss = 0\n    # if inp.shape != target.shape:\n    #     sys.exit('Input and target shapes are inconsistent')\n\n    if inp.shape[0] == 1:\n        if params is not None:\n            acc_mse_loss += MSE(\n                inp,\n                target,\n                reduction=params[\"loss_function\"][\"mse\"][\"reduction\"],\n                scaling_factor=params[\"scaling_factor\"],\n            )\n        else:\n            acc_mse_loss += MSE(inp, target)\n        # for i in range(0, params[\"model\"][\"num_classes\"]):\n        #    acc_mse_loss += MSE(inp[i], target[i], reduction=params[\"loss_function\"]['mse'][\"reduction\"])\n    else:\n        if params is not None:\n            for i in range(0, params[\"model\"][\"num_classes\"]):\n                acc_mse_loss += MSE(\n                    inp[:, i, ...],\n                    target[:, i, ...],\n                    reduction=params[\"loss_function\"][\"mse\"][\"reduction\"],\n                    scaling_factor=params[\"scaling_factor\"],\n                )\n        else:\n            for i in range(0, inp.shape[1]):\n                acc_mse_loss += MSE(inp[:, i, ...], target[:, i, ...])\n    if params is not None:\n        acc_mse_loss /= params[\"model\"][\"num_classes\"]\n    else:\n        acc_mse_loss /= inp.shape[1]\n\n    return acc_mse_loss\n\n\ndef fetch_loss_function(loss_name, params):\n\n    if isinstance(loss_name, dict):  # this is currently only happening for mse_torch\n        # check for mse_torch\n        loss_function = MSE_loss\n    elif loss_name == \"dc\":\n        loss_function = MCD_loss\n    elif loss_name == \"dc_log\":\n        loss_function = MCD_log_loss\n    elif loss_name == \"dcce\":\n        loss_function = DCCE\n    elif loss_name == \"dcce_logits\":\n        loss_function = DCCE_Logits\n    elif loss_name == \"ce\":\n        loss_function = CE\n    elif loss_name == \"mse\":\n        loss_function = MSE_loss\n    elif loss_name == \"cel\":\n        loss_function = cel\n    elif loss_name == \"kld\":\n        loss_function = KullbackLeiblerDivergence\n    elif loss_name == \"l1\":\n        loss_function = L1_loss\n    else:\n        print(\n            \"WARNING: Could not find the requested loss function '\"\n            + loss_name\n            + \"' in the implementation, using dc, instead\",\n            file=sys.stderr,\n        )\n        loss_name = \"dc\"\n        loss_function = MCD_loss\n    return loss_function\n", "path": "GANDLF/losses.py"}]}