Skip to content

Commit eafdd5b

Browse files
[pre-commit.ci] Add auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
1 parent 5f67019 commit eafdd5b

6 files changed

Lines changed: 31 additions & 39 deletions

File tree

fl4health/clients/flexible_client.py

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
from typing import Any
77

88
import torch
9-
import torch.nn as nn
109
from flwr.common.logger import log
1110
from flwr.common.typing import Config, NDArrays, Scalar
11+
from torch import nn
1212
from torch.nn.modules.loss import _Loss
1313
from torch.optim import Optimizer
1414
from 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:

fl4health/mixins/adaptive_drift_constrained.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ def set_parameters(
143143
def train_step(
144144
self: AdaptiveDriftConstrainedProtocol, input: TorchInputType, target: TorchTargetType
145145
) -> tuple[TrainingLosses, TorchPredType]:
146-
147146
losses, preds = self._compute_preds_and_losses(self.model, self.optimizers["global"], input, target)
148147
loss_clone = losses.backward["backward"].clone()
149148

@@ -207,7 +206,8 @@ def compute_penalty_loss(self: AdaptiveDriftConstrainedProtocol) -> torch.Tensor
207206

208207

209208
def apply_adaptive_drift_to_client(client_base_type: type[FlexibleClient]) -> type[FlexibleClient]:
210-
"""Dynamically create an adapted client class.
209+
"""
210+
Dynamically create an adapted client class.
211211
212212
Args:
213213
client_base_type (type[FlexibleClient]): The class to be mixed.

fl4health/mixins/personalized/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
@wrapt.decorator
1010
def ensure_protocol_compliance(func: Callable, instance: Any | None, args: Any, kwargs: Any) -> Any:
11-
"""Wrapper to ensure that a the instance is of `FlexibleClient` type.
11+
"""
12+
Wrapper to ensure that a the instance is of `FlexibleClient` type.
1213
1314
NOTE: this should only be used within a `FlexibleClient`.
1415

tests/clients/test_flexible_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from tests.test_utils.assert_metrics_dict import assert_metrics_dict
2525
from tests.test_utils.models_for_test import LinearModel
2626

27+
2728
freezegun.configure(extend_ignore_list=["transformers"]) # type: ignore
2829

2930

@@ -249,8 +250,7 @@ def mock_validate_or_test( # type: ignore
249250
fold_loss_dict_into_metrics(self.mock_metrics, self.mock_loss_dict, logging_mode)
250251
if logging_mode == LoggingMode.VALIDATION:
251252
return self.mock_loss, self.mock_metrics
252-
else:
253-
return self.mock_loss, self.mock_metrics_test
253+
return self.mock_loss, self.mock_metrics_test
254254

255255

256256
def test_subclass_raises_warning_if_override_val_step() -> None:

tests/mixins/personalized/test_ditto.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ class _TestDittoedClient(DittoPersonalizedMixin, _TestFlexibleClient):
4949

5050

5151
class _DummyParent:
52-
5352
def __init__(self) -> None:
5453
pass
5554

@@ -81,7 +80,6 @@ class _InvalidTestDittoClient(DittoPersonalizedMixin):
8180
pass
8281

8382
with pytest.raises(RuntimeError, match="This object needs to satisfy `FlexibleClientProtocolPreSetup`."):
84-
8583
_InvalidTestDittoClient(data_path=Path(""), metrics=[Accuracy()])
8684

8785

@@ -370,7 +368,6 @@ def test_val_step(
370368

371369
def test_raise_runtime_error_not_flexible_client() -> None:
372370
"""Test that an invalid parent raises RuntimeError."""
373-
374371
with pytest.raises(
375372
RuntimeError, match=re.escape("This object needs to satisfy `FlexibleClientProtocolPreSetup`.")
376373
):

tests/mixins/test_adaptive_drift_constrained.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ class _InvalidTestAdaptedClient(AdaptiveDriftConstrainedMixin):
6767
pass
6868

6969
with pytest.raises(RuntimeError, match="This object needs to satisfy `FlexibleClientProtocolPreSetup`."):
70-
7170
_InvalidTestAdaptedClient(data_path=Path(""), metrics=[Accuracy()])
7271

7372

0 commit comments

Comments
 (0)