Skip to content

Commit 9bc9d42

Browse files
authored
Merge pull request #405 from VectorInstitute/dbe/loosening_some_ruff_ignores
Loosening Some Ruff Ignores
2 parents 3f50d8f + f08602c commit 9bc9d42

59 files changed

Lines changed: 744 additions & 367 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

examples/fedllm_example/model.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
88

99

10+
EIGHT_BIT = 8
11+
FOUR_BIT = 4
12+
13+
1014
def cosine_annealing(
1115
total_round: int,
1216
current_round: int = 0,
@@ -48,9 +52,9 @@ def get_model(model_cfg: dict[str, Any]) -> torch.nn.Module:
4852
torch.nn.Module: The model.
4953
"""
5054
quantization_config = model_cfg["quantization"]
51-
if quantization_config == 4:
55+
if quantization_config == FOUR_BIT:
5256
quantization_config = BitsAndBytesConfig(load_in_4bit=True)
53-
elif quantization_config == 8:
57+
elif quantization_config == EIGHT_BIT:
5458
quantization_config = BitsAndBytesConfig(load_in_8bit=True)
5559
else:
5660
raise ValueError(f"Use 4-bit or 8-bit quantization. You passed: {quantization_config}/")

fl4health/checkpointing/state_checkpointer.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -488,13 +488,13 @@ def maybe_load_server_state(
488488
Load the state of the server from checkpoint.
489489
490490
Args:
491-
server (FlServer): server into which the attributes will be loaded
492-
model nn.Module: The model structure to be loaded as part of the server state.
493-
attributes (list[str] | None): List of attributes to load from the checkpoint. If None, all attributes
494-
specified in ``snapshot_attrs`` are loaded. Defaults to None.
491+
server (FlServer): Server into which the attributes will be loaded.
492+
model (nn.Module): The model structure to be loaded as part of the server state.
493+
attributes (list[str] | None, optional): List of attributes to load from the checkpoint. If None, all
494+
attributes specified in ``snapshot_attrs`` are loaded. Defaults to None.
495495
496496
Returns:
497-
nn.Module | None: Returns a model if a checkpoint exists to load from. Otherwise returns None
497+
nn.Module | None: Returns a model if a checkpoint exists to load from. Otherwise returns None.
498498
"""
499499
# Store server for access in functions
500500
self.server = server

fl4health/clients/basic_client.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
from fl4health.utils.typing import LogLevel, TorchFeatureType, TorchInputType, TorchPredType, TorchTargetType
3838

3939

40+
EXPECTED_OUTPUT_TUPLE_SIZE = 2
41+
42+
4043
class BasicClient(NumPyClient):
4144
def __init__(
4245
self,
@@ -140,8 +143,10 @@ def _maybe_checkpoint(self, loss: float, metrics: dict[str, Scalar], checkpoint_
140143
If checkpointer exists, maybe checkpoint model based on the provided metric values.
141144
142145
Args:
143-
loss (float): validation loss to potentially be used for checkpointing
144-
metrics (dict[str, float]): validation metrics to potentially be used for checkpointing
146+
loss (float): Validation loss to potentially be used for checkpointing.
147+
metrics (dict[str, Scalar]): Validation metrics to potentially be used for checkpointing
148+
checkpoint_mode (CheckpointMode): Whether we're doing checkpointing pre- or post-aggregation on the server
149+
side.
145150
"""
146151
self.checkpoint_and_state_module.maybe_checkpoint(self.model, loss, metrics, checkpoint_mode)
147152

@@ -439,10 +444,10 @@ def _log_header_str(
439444
the round if training by steps.
440445
441446
Args:
442-
current_round (int | None, optional): The current FL round. (Ie current
443-
server round). Defaults to None.
444-
current_epoch (int | None, optional): The current epoch of local
445-
training. Defaults to None.
447+
current_round (int | None, optional): The current FL round. (Ie current server round). Defaults to None.
448+
current_epoch (int | None, optional): The current epoch of local training. Defaults to None.
449+
logging_mode (LoggingMode, optional): The logging mode to be used in logging. This mainly changes the
450+
way in which logging is decorated. Defaults to LoggingMode.TRAIN.
446451
"""
447452
log_str = f"Current FL Round: {int(current_round)} " if current_round is not None else ""
448453
log_str += f"Current Epoch: {int(current_epoch)} " if current_epoch is not None else ""
@@ -1002,7 +1007,7 @@ def predict(self, input: TorchInputType) -> tuple[TorchPredType, TorchFeatureTyp
10021007
if isinstance(output, torch.Tensor):
10031008
return {"prediction": output}, {}
10041009
if isinstance(output, tuple):
1005-
if len(output) != 2:
1010+
if len(output) != EXPECTED_OUTPUT_TUPLE_SIZE:
10061011
raise ValueError(f"Output tuple should have length 2 but has length {len(output)}")
10071012
preds, features = output
10081013
return preds, features

fl4health/clients/constrained_fenda_client.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ def update_after_train(self, local_steps: int, loss_dict: dict[str, float], conf
152152
Args:
153153
local_steps (int): Number of steps performed during training
154154
loss_dict (dict[str, float]): Losses computed during training.
155+
config (Config): FL training configuration object.
155156
"""
156157
# Save the parameters of the old model
157158
assert isinstance(self.model, FendaModelWithFeatureState)

fl4health/clients/evaluate_client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ def __init__(
4545
"cuda"
4646
loss_meter_type (LossMeterType, optional): Type of meter used to track and compute the losses over
4747
each batch. Defaults to ``LossMeterType.AVERAGE``.
48-
model_checkpoint_path (Path | None, optional): _description_. Defaults to None.
48+
model_checkpoint_path (Path | None, optional): Path to which the model should be checkpointed. Defaults to
49+
None.
4950
reporters (Sequence[BaseReporter] | None, optional): A sequence of FL4Health reporters which the client
5051
should send data to. Defaults to None.
5152
client_name (str | None, optional): An optional client name that uniquely identifies a client.

fl4health/clients/fedrep_client.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def _prefix_loss_and_metrics_dictionaries(
122122
Args:
123123
prefix (str): Prefix to be attached to all keys of the provided dictionaries.
124124
loss_dict (dict[str, float]): Dictionary of loss values obtained during training.
125-
metrics (dict[str, Scalar]): Dictionary of metrics values measured during training
125+
metrics_dict (dict[str, Scalar]): Dictionary of metrics values measured during training.
126126
"""
127127
for loss_key in list(loss_dict):
128128
loss_dict[f"{prefix}_{loss_key}"] = loss_dict.pop(loss_key)
@@ -317,12 +317,13 @@ def train_fedrep_by_epochs(
317317
Train locally for the specified number of epochs.
318318
319319
Args:
320-
epochs (int): The number of epochs for local training.
321-
current_round (int | None): The current FL round.
320+
head_epochs (int): The number of epochs for local training of the head module.
321+
rep_epochs (int): The number of epochs for local training of the representation module
322+
current_round (int | None, optional): The current FL round. Defaults to None.
322323
323324
Returns:
324325
tuple[dict[str, float], dict[str, Scalar]]: The loss and metrics dictionary from the local training.
325-
Loss is a dictionary of one or more losses that represent the different components of the loss.
326+
Loss is a dictionary of one or more losses that represent the different components of the loss.
326327
"""
327328
# First we train the head module for head_epochs with the representations frozen in place
328329
self._prepare_train_head()
@@ -356,11 +357,13 @@ def train_fedrep_by_steps(
356357
Train locally for the specified number of steps.
357358
358359
Args:
359-
steps (int): The number of steps to train locally.
360+
head_steps (int): The number of steps to train locally for the head model.
361+
rep_steps (int): The number of steps to train locally for the representation model
362+
current_round (int | None, optional): What round of FL training we're currently on. Defaults to None.
360363
361364
Returns:
362365
tuple[dict[str, float], dict[str, Scalar]]: The loss and metrics dictionary from the local training.
363-
Loss is a dictionary of one or more losses that represent the different components of the loss.
366+
Loss is a dictionary of one or more losses that represent the different components of the loss.
364367
"""
365368
assert isinstance(self.model, FedRepModel)
366369
# First we train the head module for head_steps with the representations frozen in place

fl4health/clients/flexible_client.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
from fl4health.utils.typing import TorchFeatureType, TorchInputType, TorchPredType, TorchTargetType
1818

1919

20+
EXPECTED_OUTPUT_TUPLE_SIZE = 2
21+
22+
2023
class FlexibleClient(BasicClient):
2124
def __init__(
2225
self,
@@ -296,7 +299,7 @@ def predict_with_model(
296299
if isinstance(output, torch.Tensor):
297300
return {"prediction": output}, {}
298301
if isinstance(output, tuple):
299-
if len(output) != 2:
302+
if len(output) != EXPECTED_OUTPUT_TUPLE_SIZE:
300303
raise ValueError(f"Output tuple should have length 2 but has length {len(output)}")
301304
preds, features = output
302305
return preds, features

fl4health/clients/nnunet_client.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ def __init__(
138138
No checkpointing (state or model) is done if not provided. Defaults to None.
139139
reporters (Sequence[BaseReporter], optional): A sequence of FL4Health reporters which the client should
140140
send data to.
141+
client_name (str | None, optional): Name of the client. If None the class will set a default and random
142+
name. Defaults to None.
141143
nnunet_trainer_class (type[nnUNetTrainer]): A ``nnUNetTrainer`` constructor. Useful for passing custom
142144
``nnUNetTrainer``. Defaults to the standard nnUNetTrainer class. Must match the
143145
``nnunet_trainer_class`` passed to the ``NnunetServer``.
@@ -340,7 +342,13 @@ def get_lr_scheduler(self, optimizer_key: str, config: Config) -> _LRScheduler:
340342
this method to set your own LR scheduler.
341343
342344
Args:
343-
config (Config): The server config. This method will look for the
345+
optimizer_key (str): Key of the optimizer to which the scheduler will be applied.
346+
config (Config): The server config. This method will determine the total number of steps that will be
347+
applied across all server rounds on FL training.
348+
349+
Raises:
350+
ValueError: Thrown if the configuration does not contain either a steps or epochs specification.
351+
344352
Returns:
345353
_LRScheduler: The default nnunet LR Scheduler for nnunetv2 2.5.1
346354
"""
@@ -904,7 +912,7 @@ def update_before_train(self, current_server_round: int) -> None:
904912
gc.collect() # Cleans up unused variables
905913
# As the linked issue above points out, calling gc.freeze() greatly reduces the
906914
# overhead of garbage collection. (from 1.5s to 0.005s)
907-
if current_server_round == 2:
915+
if current_server_round == 2: # noqa: PLR2004
908916
# Collect runs even faster if we freeze after the end of the first iteration
909917
# Likely because a lot of variables are created in the first pass. If we
910918
# freeze before the first pass, gc.collect has to check all those variables

fl4health/clients/scaffold_client.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ def set_parameters(self, parameters: NDArrays, config: Config, fitting_round: bo
123123
parameters (NDArrays): Parameters have information about model state to be added to the relevant client
124124
model and also the server control variates (initial or after aggregation)
125125
config (Config): The config is sent by the FL server to allow for customization in the function if desired.
126+
fitting_round (bool): Which fitting round (i.e. server round of fitting) that we're on.
126127
"""
127128
assert self.model is not None and self.parameter_exchanger is not None
128129

@@ -309,12 +310,6 @@ def setup_client(self, config: Config) -> None:
309310

310311

311312
class DPScaffoldClient(ScaffoldClient, InstanceLevelDpClient):
312-
"""
313-
Federated Learning client for Instance Level Differentially Private Scaffold strategy.
314-
315-
Implemented as specified in https://arxiv.org/abs/2111.09278
316-
"""
317-
318313
def __init__(
319314
self,
320315
data_path: Path,
@@ -326,6 +321,30 @@ def __init__(
326321
progress_bar: bool = False,
327322
client_name: str | None = None,
328323
) -> None:
324+
"""
325+
Federated Learning client for Instance Level Differentially Private Scaffold strategy.
326+
327+
Implemented as specified in https://arxiv.org/abs/2111.09278
328+
329+
Args:
330+
data_path (Path): path to the data to be used to load the data for client-side training
331+
metrics (Sequence[Metric]): Metrics to be computed based on the labels and predictions of the client model
332+
device (torch.device): Device indicator for where to send the model, batches, labels etc. Often "cpu" or
333+
"cuda"
334+
loss_meter_type (LossMeterType, optional): Type of meter used to track and compute the losses over
335+
each batch. Defaults to ``LossMeterType.AVERAGE``.
336+
checkpoint_and_state_module (ClientCheckpointAndStateModule | None, optional): A module meant to handle
337+
both checkpointing and state saving. The module, and its underlying model and state checkpointing
338+
components will determine when and how to do checkpointing during client-side training.
339+
No checkpointing (state or model) is done if not provided. Defaults to None.
340+
reporters (Sequence[BaseReporter] | None, optional): A sequence of FL4Health reporters which the client
341+
should send data to. Defaults to None.
342+
progress_bar (bool, optional): Whether or not to display a progress bar during client training and
343+
validation. Uses ``tqdm``. Defaults to False.
344+
client_name (str | None, optional): n optional client name that uniquely identifies a client.
345+
If not passed, a hash is randomly generated. Client state will use this as part of its state file
346+
name. Defaults to None.
347+
"""
329348
ScaffoldClient.__init__(
330349
self,
331350
data_path=data_path,

fl4health/feature_alignment/string_columns_transformer.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ def __init__(self, transformer: TextFeatureTransformer):
2020
def fit(self, x: pd.DataFrame, y: pd.DataFrame | None = None) -> TextMulticolumnTransformer:
2121
"""
2222
Fit the transformer to the provided dataframe. The dataframe should have multiple string columns
23-
The transformer is fit on the appended text from all columns in the ``X`` dataframe.
23+
The transformer is fit on the appended text from all columns in the ``x`` dataframe.
2424
2525
Args:
26-
X (pd.DataFrame): Columns on which to fit the transformer
26+
x (pd.DataFrame): Columns on which to fit the transformer
2727
y (pd.DataFrame | None, optional): Not used. Defaults to None.
2828
2929
Returns:
@@ -35,10 +35,10 @@ def fit(self, x: pd.DataFrame, y: pd.DataFrame | None = None) -> TextMulticolumn
3535

3636
def transform(self, x: pd.DataFrame) -> pd.DataFrame:
3737
"""
38-
Transforms the concatenation of all columns of text in the ``X`` dataframe.
38+
Transforms the concatenation of all columns of text in the ``x`` dataframe.
3939
4040
Args:
41-
X (pd.DataFrame): Dataframe of text-based columns to be transformed
41+
x (pd.DataFrame): Dataframe of text-based columns to be transformed
4242
4343
Returns:
4444
pd.DataFrame: Transformed dataframe.
@@ -61,10 +61,10 @@ def __init__(self, transformer: TextFeatureTransformer):
6161
def fit(self, x: pd.DataFrame, y: pd.DataFrame | None = None) -> TextColumnTransformer:
6262
"""
6363
Fit the transformer to the provided dataframe. The dataframe should have a single string column
64-
The transformer is fit on the text from the single columns in the ``X`` dataframe.
64+
The transformer is fit on the text from the single columns in the ``x`` dataframe.
6565
6666
Args:
67-
X (pd.DataFrame): Column on which to fit the transformer
67+
x (pd.DataFrame): Column on which to fit the transformer
6868
y (pd.DataFrame | None, optional): Not used. Defaults to None.
6969
7070
Returns:
@@ -76,10 +76,10 @@ def fit(self, x: pd.DataFrame, y: pd.DataFrame | None = None) -> TextColumnTrans
7676

7777
def transform(self, x: pd.DataFrame) -> pd.DataFrame:
7878
"""
79-
Transforms the concatenation of a single column of text in the ``X`` dataframe.
79+
Transforms the concatenation of a single column of text in the ``x`` dataframe.
8080
8181
Args:
82-
X (pd.DataFrame): Dataframe of text-based column to be transformed
82+
x (pd.DataFrame): Dataframe of text-based column to be transformed
8383
8484
Returns:
8585
pd.DataFrame: Transformed dataframe.

0 commit comments

Comments
 (0)