Skip to content

Commit 2c756e9

Browse files
committed
wip
1 parent 81e5df5 commit 2c756e9

1 file changed

Lines changed: 46 additions & 30 deletions

File tree

fl4health/clients/nnunet_client.py

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -612,27 +612,14 @@ def setup_client(self, config: Config) -> None:
612612
# We have to call parent method after setting up nnunet trainer
613613
super().setup_client(config)
614614

615-
def predict(self, input: TorchInputType) -> tuple[TorchPredType, dict[str, torch.Tensor]]:
616-
"""
617-
Generate model outputs. Overridden because nnunets outputs lists when deep supervision is on so we have to
618-
reformat the output into dicts.
619-
620-
Additionally if device type is cuda, loss computed in mixed precision.
621-
622-
Args:
623-
input (TorchInputType): The model inputs
624-
625-
Returns:
626-
tuple[TorchPredType, dict[str, torch.Tensor]]: A tuple in which the first element model outputs indexed by
627-
name. The second element is unused by this subclass and therefore is always an empty dict
628-
"""
615+
def _predict(self, model: torch.nn.Module, input: TorchInputType) -> tuple[TorchPredType, dict[str, torch.Tensor]]:
629616
if isinstance(input, torch.Tensor):
630617
# If device type is cuda, nnUNet defaults to mixed precision forward pass
631618
if self.device.type == "cuda":
632619
with torch.autocast(self.device.type, enabled=True):
633-
output = self.model(input)
620+
output = model(input)
634621
else:
635-
output = self.model(input)
622+
output = model(input)
636623
else:
637624
raise TypeError('"input" must be of type torch.Tensor for nnUNetClient')
638625

@@ -648,26 +635,28 @@ def predict(self, input: TorchInputType) -> tuple[TorchPredType, dict[str, torch
648635
"Was expecting nnunet model output to be either a torch.Tensor or a list/tuple of torch.Tensors"
649636
)
650637

651-
def compute_loss_and_additional_losses(
652-
self,
653-
preds: TorchPredType,
654-
features: dict[str, torch.Tensor],
655-
target: TorchTargetType,
656-
) -> tuple[torch.Tensor, dict[str, torch.Tensor] | None]:
638+
def predict(self, input: TorchInputType) -> tuple[TorchPredType, dict[str, torch.Tensor]]:
657639
"""
658-
Checks the pred and target types and computes the loss. If device type is cuda, loss computed in mixed
659-
precision.
640+
Generate model outputs. Overridden because nnunets outputs lists when deep supervision is on so we have to
641+
reformat the output into dicts.
642+
643+
Additionally if device type is cuda, loss computed in mixed precision.
660644
661645
Args:
662-
preds (TorchPredType): Dictionary of model output tensors indexed by name
663-
features (dict[str, torch.Tensor]): Not used by this subclass
664-
target (TorchTargetType): The targets to evaluate the predictions with. If multiple prediction tensors
665-
are given, target must be a dictionary with the same number of tensors
646+
input (TorchInputType): The model inputs
666647
667648
Returns:
668-
tuple[torch.Tensor, dict[str, torch.Tensor] | None]: A tuple where the first element is the loss and the
669-
second element is an optional additional loss
649+
tuple[TorchPredType, dict[str, torch.Tensor]]: A tuple in which the first element model outputs indexed by
650+
name. The second element is unused by this subclass and therefore is always an empty dict
670651
"""
652+
return self._predict(self.model, input)
653+
654+
def _special_compute_loss_and_additional_losses(
655+
self,
656+
preds: TorchPredType,
657+
features: dict[str, torch.Tensor],
658+
target: TorchTargetType,
659+
) -> tuple[torch.Tensor, dict[str, torch.Tensor] | None]:
671660
# If deep supervision is turned on we must convert loss and target dicts into lists
672661
loss_preds = prepare_loss_arg(preds)
673662
loss_targets = prepare_loss_arg(target)
@@ -692,6 +681,28 @@ def compute_loss_and_additional_losses(
692681

693682
return loss
694683

684+
def compute_loss_and_additional_losses(
685+
self,
686+
preds: TorchPredType,
687+
features: dict[str, torch.Tensor],
688+
target: TorchTargetType,
689+
) -> tuple[torch.Tensor, dict[str, torch.Tensor] | None]:
690+
"""
691+
Checks the pred and target types and computes the loss. If device type is cuda, loss computed in mixed
692+
precision.
693+
694+
Args:
695+
preds (TorchPredType): Dictionary of model output tensors indexed by name
696+
features (dict[str, torch.Tensor]): Not used by this subclass
697+
target (TorchTargetType): The targets to evaluate the predictions with. If multiple prediction tensors
698+
are given, target must be a dictionary with the same number of tensors
699+
700+
Returns:
701+
tuple[torch.Tensor, dict[str, torch.Tensor] | None]: A tuple where the first element is the loss and the
702+
second element is an optional additional loss
703+
"""
704+
return self._special_compute_loss_and_additional_losses(preds, features, target)
705+
695706
def mask_data(self, pred: torch.Tensor, target: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
696707
"""
697708
Masks the pred and target tensors according to nnunet ``ignore_label``. The number of classes in the input
@@ -748,8 +759,13 @@ def update_metric_manager(
748759
target (TorchTargetType): the targets generated by the dataloader to evaluate the preds with
749760
metric_manager (MetricManager): the metric manager to update
750761
"""
762+
preds = {k: v for k, v in preds.items() if "local" in k}
763+
# remove prefix
764+
preds = {k.replace("local-", ""): v for k, v in preds.items()}
765+
751766
if len(preds) > 1:
752767
# for nnunet the first pred in the output list is the main one
768+
log(DEBUG, f"preds keys: {preds.keys()}")
753769
m_pred = convert_deep_supervision_dict_to_list(preds)[0]
754770

755771
if isinstance(target, torch.Tensor):

0 commit comments

Comments
 (0)