66from typing import Any
77
88import torch
9- import torch .nn as nn
109from flwr .common .logger import log
1110from flwr .common .typing import Config , NDArrays , Scalar
11+ from torch import nn
1212from torch .nn .modules .loss import _Loss
1313from torch .optim import Optimizer
1414from torch .optim .lr_scheduler import LRScheduler
@@ -74,7 +74,6 @@ def __init__(
7474 If not passed, a hash is randomly generated. Client state will use this as part of its state file
7575 name. Defaults to None.
7676 """
77-
7877 self .data_path = data_path
7978 self .device = device
8079 self .metrics = metrics
@@ -202,12 +201,11 @@ def get_parameters(self, config: Config) -> NDArrays:
202201
203202 # Need all parameters even if normally exchanging partial
204203 return FullParameterExchanger ().push_parameters (self .model , config = config )
205- else :
206- assert self .model is not None and self .parameter_exchanger is not None
207- # If the client has early stopping module and the patience is None, we load the best saved state
208- # to send the best checkpointed local model's parameters to the server
209- self ._maybe_load_saved_best_local_model_state ()
210- return self .parameter_exchanger .push_parameters (self .model , config = config )
204+ assert self .model is not None and self .parameter_exchanger is not None
205+ # If the client has early stopping module and the patience is None, we load the best saved state
206+ # to send the best checkpointed local model's parameters to the server
207+ self ._maybe_load_saved_best_local_model_state ()
208+ return self .parameter_exchanger .push_parameters (self .model , config = config )
211209
212210 def _maybe_load_saved_best_local_model_state (self ) -> None :
213211 if self .early_stopper is not None and self .early_stopper .patience is None :
@@ -280,7 +278,7 @@ def process_config(self, config: Config) -> tuple[int | None, int | None, int, b
280278 # Parse config to determine train by steps or train by epochs
281279 if ("local_epochs" in config ) and ("local_steps" in config ):
282280 raise ValueError ("Config cannot contain both local_epochs and local_steps. Please specify only one." )
283- elif "local_epochs" in config :
281+ if "local_epochs" in config :
284282 local_epochs = narrow_dict_type (config , "local_epochs" , int )
285283 local_steps = None
286284 elif "local_steps" in config :
@@ -479,7 +477,6 @@ def _log_header_str(
479477 current_epoch (int | None, optional): The current epoch of local
480478 training. Defaults to None.
481479 """
482-
483480 log_str = f"Current FL Round: { int (current_round )} " if current_round is not None else ""
484481 log_str += f"Current Epoch: { int (current_epoch )} " if current_epoch is not None else ""
485482
@@ -591,7 +588,8 @@ def update_metric_manager(
591588 def _compute_preds_and_losses (
592589 self , model : nn .Module , optimizer : Optimizer , input : TorchInputType , target : TorchTargetType
593590 ) -> tuple [TrainingLosses , TorchPredType ]:
594- """Helper method within the train step for computing preds and losses.
591+ """
592+ Helper method within the train step for computing preds and losses.
595593
596594 NOTE: Subclasses should implement this helper method if there is a need
597595 to specialize this part of the overall train step.
@@ -620,7 +618,8 @@ def _compute_preds_and_losses(
620618 def _apply_backwards_on_losses_and_take_step (
621619 self , model : nn .Module , optimizer : Optimizer , losses : TrainingLosses
622620 ) -> TrainingLosses :
623- """Helper method within the train step for applying backwards on losses and taking step with optimizer.
621+ """
622+ Helper method within the train step for applying backwards on losses and taking step with optimizer.
624623
625624 NOTE: Subclasses should implement this helper method if there is a need
626625 to specialize this part of the overall train step.
@@ -643,7 +642,8 @@ def _apply_backwards_on_losses_and_take_step(
643642 def _train_step_with_model_and_optimizer (
644643 self , model : torch .nn .Module , optimizer : Optimizer , input : TorchInputType , target : TorchTargetType
645644 ) -> tuple [TrainingLosses , TorchPredType ]:
646- """Helper train step method that allows for injection of model and optimizer.
645+ """
646+ Helper train step method that allows for injection of model and optimizer.
647647
648648 NOTE: Subclasses should implement this method if there is a need to specialize
649649 the train_step logic.
@@ -656,7 +656,6 @@ def _train_step_with_model_and_optimizer(
656656 tuple[TrainingLosses, TorchPredType]: The losses object from the train step along with
657657 a dictionary of any predictions produced by the model.
658658 """
659-
660659 losses , preds = self ._compute_preds_and_losses (model , optimizer , input , target )
661660 losses = self ._apply_backwards_on_losses_and_take_step (model , optimizer , losses )
662661
@@ -681,7 +680,8 @@ def train_step(self, input: TorchInputType, target: TorchTargetType) -> tuple[Tr
681680 def _val_step_with_model (
682681 self , model : nn .Module , input : TorchInputType , target : TorchTargetType
683682 ) -> tuple [EvaluationLosses , TorchPredType ]:
684- """Helper method for val_step that allows for injection of model.
683+ """
684+ Helper method for val_step that allows for injection of model.
685685
686686 NOTE: Subclasses should implement this method if there is a need to
687687 specialize the val_step logic.
@@ -694,7 +694,6 @@ def _val_step_with_model(
694694 tuple[EvaluationLosses, TorchPredType]: The losses object from the val step along with a dictionary of the
695695 predictions produced by the model.
696696 """
697-
698697 # Get preds and compute loss
699698 with torch .no_grad ():
700699 preds , features = self .predict_with_model (model , input )
@@ -715,7 +714,6 @@ def val_step(self, input: TorchInputType, target: TorchTargetType) -> tuple[Eval
715714 tuple[EvaluationLosses, TorchPredType]: The losses object from the val step along with a dictionary of the
716715 predictions produced by the model.
717716 """
718-
719717 return self ._val_step_with_model (self .model , input , target )
720718
721719 def train_by_epochs (
@@ -874,7 +872,6 @@ def _validate_by_steps(
874872 Returns:
875873 tuple[float, dict[str, Scalar]]: The loss and a dictionary of metrics from evaluation.
876874 """
877-
878875 assert self .num_validation_steps is not None , "num_validation_steps must be defined to use this function"
879876
880877 self .model .eval ()
@@ -1047,9 +1044,9 @@ def setup_client(self, config: Config) -> None:
10471044 # batch_size * num_validation_steps
10481045 self .num_val_samples = len (self .val_loader .dataset ) # type: ignore
10491046 if self .num_validation_steps is not None :
1050- assert (
1051- self . val_loader . batch_size is not None
1052- ), "Validation batch size must be defined if we want to limit the number of validation steps"
1047+ assert self . val_loader . batch_size is not None , (
1048+ "Validation batch size must be defined if we want to limit the number of validation steps"
1049+ )
10531050 self .num_val_samples = self .num_validation_steps * self .val_loader .batch_size
10541051
10551052 if self .test_loader :
@@ -1087,7 +1084,8 @@ def get_parameter_exchanger(self, config: Config) -> ParameterExchanger:
10871084 def predict_with_model (
10881085 self , model : torch .nn .Module , input : TorchInputType
10891086 ) -> tuple [TorchPredType , TorchFeatureType ]:
1090- """Helper predict method that allows for injection of model.
1087+ """
1088+ Helper predict method that allows for injection of model.
10911089
10921090 NOTE: Subclasses should implement this method if there is need to specialize
10931091 the predict logic of the client.
@@ -1110,7 +1108,6 @@ def predict_with_model(
11101108 ValueError: Occurs when something other than a tensor or dict of tensors is returned by the model
11111109 forward.
11121110 """
1113-
11141111 if isinstance (input , torch .Tensor ):
11151112 output = model (input )
11161113 elif isinstance (input , dict ):
@@ -1123,15 +1120,14 @@ def predict_with_model(
11231120
11241121 if isinstance (output , dict ):
11251122 return output , {}
1126- elif isinstance (output , torch .Tensor ):
1123+ if isinstance (output , torch .Tensor ):
11271124 return {"prediction" : output }, {}
1128- elif isinstance (output , tuple ):
1125+ if isinstance (output , tuple ):
11291126 if len (output ) != 2 :
11301127 raise ValueError (f"Output tuple should have length 2 but has length { len (output )} " )
11311128 preds , features = output
11321129 return preds , features
1133- else :
1134- raise ValueError ("Model forward did not return a tensor, dictionary of tensors, or tuple of tensors" )
1130+ raise ValueError ("Model forward did not return a tensor, dictionary of tensors, or tuple of tensors" )
11351131
11361132 def compute_loss_and_additional_losses (
11371133 self , preds : TorchPredType , features : TorchFeatureType , target : TorchTargetType
@@ -1328,7 +1324,6 @@ def update_lr_schedulers(self, step: int | None = None, epoch: int | None = None
13281324 step (int | None): If using ``local_steps``, current step of this round. Otherwise None.
13291325 epoch (int | None): If using ``local_epochs`` current epoch of this round. Otherwise None.
13301326 """
1331-
13321327 assert (step is None ) ^ (epoch is None )
13331328
13341329 for lr_scheduler in self .lr_schedulers .values ():
@@ -1396,7 +1391,8 @@ def update_before_epoch(self, epoch: int) -> None:
13961391 pass
13971392
13981393 def _transform_gradients_with_model (self , model : torch .nn .Module , losses : TrainingLosses ) -> None :
1399- """Helper transform gradients method that allows for injection of model.
1394+ """
1395+ Helper transform gradients method that allows for injection of model.
14001396
14011397 NOTE: Subclasses should implement this helper should there be a need to specialize the logic
14021398 for transforming gradients.
@@ -1405,7 +1401,6 @@ def _transform_gradients_with_model(self, model: torch.nn.Module, losses: Traini
14051401 model (torch.nn.Module): the model used to generate predictions to compute losses
14061402 losses (TrainingLosses): The losses object from the train step
14071403 """
1408-
14091404 pass
14101405
14111406 def transform_gradients (self , losses : TrainingLosses ) -> None :
0 commit comments