Skip to content

Commit 3dbe35d

Browse files
committed
fix: address review feedback — fix class_index, eliminate double-masking, add docs
Signed-off-by: Rusheel Sharma <rusheelhere@gmail.com>
1 parent e9dba63 commit 3dbe35d

3 files changed

Lines changed: 17 additions & 14 deletions

File tree

monai/losses/unified_focal_loss.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -225,12 +225,8 @@ def __init__(
225225
self.gamma = gamma
226226
self.delta = delta
227227
self.weight: float = weight
228-
self.asy_focal_loss = AsymmetricFocalLoss(
229-
to_onehot_y=False, gamma=self.gamma, delta=self.delta, ignore_index=ignore_index
230-
)
231-
self.asy_focal_tversky_loss = AsymmetricFocalTverskyLoss(
232-
to_onehot_y=False, gamma=self.gamma, delta=self.delta, ignore_index=ignore_index
233-
)
228+
self.asy_focal_loss = AsymmetricFocalLoss(to_onehot_y=False, gamma=self.gamma, delta=self.delta)
229+
self.asy_focal_tversky_loss = AsymmetricFocalTverskyLoss(to_onehot_y=False, gamma=self.gamma, delta=self.delta)
234230
self.ignore_index = ignore_index
235231

236232
def forward(self, y_pred: torch.Tensor, y_true: torch.Tensor) -> torch.Tensor:
@@ -283,14 +279,11 @@ def forward(self, y_pred: torch.Tensor, y_true: torch.Tensor) -> torch.Tensor:
283279

284280
mask = create_ignore_mask(original_y_true, self.ignore_index)
285281

286-
use_mask = self.ignore_index is not None and (self.ignore_index < 0 or self.ignore_index >= self.num_classes)
287-
if use_mask:
288-
y_pred_masked, y_true_masked = mask_loss_inputs(y_pred, y_true, self.ignore_index, mask=mask)
289-
else:
290-
y_pred_masked, y_true_masked = y_pred, y_true
282+
if self.ignore_index is not None:
283+
y_pred, y_true = mask_loss_inputs(y_pred, y_true, self.ignore_index, mask=mask)
291284

292-
asy_focal_loss = self.asy_focal_loss(y_pred_masked, y_true_masked)
293-
asy_focal_tversky_loss = self.asy_focal_tversky_loss(y_pred_masked, y_true_masked)
285+
asy_focal_loss = self.asy_focal_loss(y_pred, y_true)
286+
asy_focal_tversky_loss = self.asy_focal_tversky_loss(y_pred, y_true)
294287

295288
loss: torch.Tensor = self.weight * asy_focal_loss + (1 - self.weight) * asy_focal_tversky_loss
296289

monai/metrics/surface_dice.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ def compute_surface_dice(
282282
spacing=spacing_list[b],
283283
use_subvoxels=use_subvoxels,
284284
symmetric=True,
285-
class_index=c,
285+
class_index=absolute_c,
286286
warn_empty=warn_empty,
287287
)
288288
boundary_correct: int | torch.Tensor | float

monai/metrics/utils.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ def create_ignore_mask(y: torch.Tensor, ignore_index: int | None) -> torch.Tenso
106106
values (e.g., -1): they are only meaningful class labels for label-encoded targets. For
107107
one-hot inputs, negative values fall through to the sentinel path (masking all-zero pixels).
108108
109+
For one-hot inputs with a valid class index, the mask zeroes all channels at pixels
110+
where the ignored class is present (spatial masking). This differs from per-channel
111+
exclusion — every pixel belonging to the ignored class is excluded from ALL class scores,
112+
not just the score for that class.
113+
109114
Returns:
110115
Mask tensor of shape (B, 1, H, W, [D]) where 1=valid, 0=ignore.
111116
Returns None if ignore_index is None.
@@ -460,6 +465,11 @@ def get_edge_surface_distance(
460465
areas = (areas[0], areas[0])
461466
elif len(areas) != 2:
462467
# Unexpected length, create empty tensors
468+
warnings.warn(
469+
f"Unexpected number of area tensors from get_mask_edges: {len(areas)}, expected 2. "
470+
"Falling back to empty tensors.",
471+
stacklevel=2,
472+
)
463473
areas = (torch.tensor([], device=y_pred.device), torch.tensor([], device=y_pred.device))
464474

465475
out = convert_to_tensor(((edges_pred, edges_gt), distances, tuple(areas)), device=y_pred.device) # type: ignore[no-any-return]

0 commit comments

Comments
 (0)