diff --git a/declearn/aggregator/_api.py b/declearn/aggregator/_api.py index d8817dee83b5c027dd825b19940fddf36d654959..468b837b520c2cdd0e86a8d6b644e381c341ff9c 100644 --- a/declearn/aggregator/_api.py +++ b/declearn/aggregator/_api.py @@ -43,7 +43,23 @@ T = TypeVar("T") @dataclasses.dataclass class ModelUpdates(Aggregate, base_cls=True, register=True): - """Base dataclass for model updates' sharing and aggregation.""" + """Base dataclass for model updates' sharing and aggregation. + + Each and every `Aggregator` subclass is expected to be coupled with + one (or multiple) `ModelUpdates` (sub)type(s), that define which data + is exchanged and how it is aggregated across a network of peers. An + instance resulting from the aggregation of multiple peers' data may + be passed to an appropriate `Aggregator` instance for finalization + into a `Vector` of model updates. + + This class also defines whether contents are compatible with secure + aggregation, and whether some fields should remain in cleartext no + matter what. + + Note that subclasses are automatically type-registered, and should be + decorated as `dataclasses.dataclass`. To prevent registration, simply + pass `register=False` at inheritance. + """ updates: Vector weights: Union[int, float] diff --git a/declearn/messaging/__init__.py b/declearn/messaging/__init__.py index 36e3a96502d77ac6231db82bc9ba89e22df01f3d..17f5e5e42fd6be0fbe6566dbcd68817937447f67 100644 --- a/declearn/messaging/__init__.py +++ b/declearn/messaging/__init__.py @@ -22,7 +22,7 @@ Message API and tools * [Message][declearn.messaging.Message]: Abstract base dataclass to define parsable messages. -* [SerializedMessage][declearn.messaging.SerializedMessage]]: +* [SerializedMessage][declearn.messaging.SerializedMessage]: Container for serialized Message instances. diff --git a/declearn/metrics/_api.py b/declearn/metrics/_api.py index e655a8c3af3ced33e0a3fd474c5312c4c66143ec..04405777044158eae800e14dfb8f20073cc9847f 100644 --- a/declearn/metrics/_api.py +++ b/declearn/metrics/_api.py @@ -41,7 +41,21 @@ __all__ = [ class MetricState( Aggregate, base_cls=True, register=False, metaclass=abc.ABCMeta ): - """Abstract base class for Metrics intermediate aggregatable states.""" + """Abstract base class for Metrics intermediate aggregatable states. + + Each and every `Metric` subclass is expected to be coupled with one + (or multiple) `MetricState` subtypes, which are used to exchange and + aggregate partial results across a network of peers, which can in the + end be passed to a single `Metric` instance for metrics' finalization. + + This class also defines whether contents are compatible with secure + aggregation, and whether some fields should remain in cleartext no + matter what. + + Note that subclasses are automatically type-registered, and should be + decorated as `dataclasses.dataclass`. To prevent registration, simply + pass `register=False` at inheritance. + """ _group_key = "MetricState" diff --git a/declearn/optimizer/modules/_api.py b/declearn/optimizer/modules/_api.py index 4aab241d8461cb08f106cc163f6d9100ba787f90..bbc13e80e2b3a17a10baf0deab0a85736244c5d1 100644 --- a/declearn/optimizer/modules/_api.py +++ b/declearn/optimizer/modules/_api.py @@ -42,7 +42,22 @@ T = TypeVar("T") @dataclasses.dataclass class AuxVar(Aggregate, base_cls=True, register=False, metaclass=abc.ABCMeta): - """Abstract base class for OptiModule auxiliary variables.""" + """Abstract base class for OptiModule auxiliary variables. + + Each and every `OptiModule` subclass that requires information to be + exchanged is expected to be coupled with one (or multiple) `AuxVar` + subtype(s). These may be used to transmit information from a server + to its clients, and/or to exchange and aggregate data from clients + into a single `AuxVar` instance to be processed by the server. + + This class also defines whether contents are compatible with secure + aggregation, and whether some fields should remain in cleartext no + matter what. + + Note that subclasses are automatically type-registered, and should be + decorated as `dataclasses.dataclass`. To prevent registration, simply + pass `register=False` at inheritance. + """ _group_key = "AuxVar" diff --git a/docs/devs-guide/contribute.md b/docs/devs-guide/contribute.md index f1e7280ecbedfccce8da317708375a56d6c39602..d69577d43162ba8f6286d21ab7ef4d9519fe83e7 100644 --- a/docs/devs-guide/contribute.md +++ b/docs/devs-guide/contribute.md @@ -60,7 +60,7 @@ The **coding rules** are fairly simple: are detailed in the [docstrings style guide](./docs-style.md). - Type-hint the code, abiding by [PEP 484](https://peps.python.org/pep-0484/); note that the use of Any and of "type: ignore" comments is authorized, but - should be remain sparse. + should remain parsimonious. - Lint your code with [mypy](http://mypy-lang.org/) (for static type checking) and [pylint](https://pylint.pycqa.org/en/latest/) (for more general linting); do use "type: ..." and "pylint: disable=..." comments where you think it diff --git a/docs/user-guide/fl_process.md b/docs/user-guide/fl_process.md index 2e68a465f492ff1e0391a76ca422dfdc11f6e93b..6972092b14e41f2196f6978a66b0702759549a68 100644 --- a/docs/user-guide/fl_process.md +++ b/docs/user-guide/fl_process.md @@ -46,16 +46,17 @@ exposed here. #### (Optional) Metadata exchange -- This step is optional, and depends on the trained model's requirement - for dataset information (typically, features shape and/or dtype). +This step is optional, and depends on the trained model's requirement +for dataset information (typically, features shape and/or dtype). + - Server: - - query clients for targetted metadata about the local training datasets + - query clients for targetted metadata about the local training datasets - Client: - - collect and send back queried metadata + - collect and send back queried metadata - messaging: (MetadataQuery <-> MetadataReply) - Server: - - validate and aggregate received information - - pass it to the model so as to finalize its initialization + - validate and aggregate received information + - pass it to the model so as to finalize its initialization #### Initialization of the federated optimization problem @@ -68,8 +69,9 @@ exposed here. #### (Optional) Local differential privacy setup -- This step is optional; a flag in the InitRequest at the previous step - indicates to clients that it is to happen, as a secondary substep. +This step is optional; a flag in the InitRequest at the previous step +indicates to clients that it is to happen, as a secondary substep. + - Server: - send hyper-parameters to set up local differential privacy, including dp-specific hyper-parameters and information on the planned training diff --git a/docs/user-guide/optimizer.md b/docs/user-guide/optimizer.md index a57dda61872c7538ee3189fb0a177291a68c3479..0579f58f2583568f54d0b2d6c5196f2d105cf2b2 100644 --- a/docs/user-guide/optimizer.md +++ b/docs/user-guide/optimizer.md @@ -448,7 +448,7 @@ Declearn introduces the notion of "auxiliary variables" to cover such cases: `Optimizer.collect_aux_var` and `process_aux_var`, which orchestrate calls to the plugged-in modules' methods of the same name. - Exchanged information is formatted via dedicated `AuxVar` data structures - (inheriting `declearn.optimizer.module.AuxVar`), that define how to aggregate + (inheriting `declearn.optimizer.modules.AuxVar`) that define how to aggregate peers' data, and indicate how to use secure aggregation on top of it (when it is possible to do so). diff --git a/docs/user-guide/package.md b/docs/user-guide/package.md index 4ac2de145d0afb14d727cd67ea6a4b1172ad295c..76c0a32b03e45aa5d128958d5a308de135b1a00d 100644 --- a/docs/user-guide/package.md +++ b/docs/user-guide/package.md @@ -14,6 +14,8 @@ The package is organized into the following submodules:   Data interfacing API and implementations. - `main`:<br/>   Main classes implementing a Federated Learning process. +- `messaging`:<br/> +   API and default classes to define parsable messages for applications. - `metrics`:<br/>   Iterative and federative evaluation metrics computation tools. - `model`:<br/> @@ -24,6 +26,8 @@ The package is organized into the following submodules:   Type hinting utils, defined and exposed for code readability purposes. - `utils`:<br/>   Shared utils used (extensively) across all of declearn. +- `version`:<br/> +   DecLearn version information, as hard-coded constants. ## Main abstractions @@ -34,7 +38,9 @@ well as references on how to extend the support of `declearn` backend (notably, (de)serialization and configuration utils) to new custom concrete implementations inheriting the abstraction. -### `Model` +### Model and Tensors + +#### `Model` - Import: `declearn.model.api.Model` - Object: Interface framework-specific machine learning models. - Usage: Compute gradients, apply updates, compute loss... @@ -44,7 +50,7 @@ new custom concrete implementations inheriting the abstraction. - `declearn.model.torch.TorchModel` - Extend: use `declearn.utils.register_type(group="Model")` -### `Vector` +#### `Vector` - Import: `declearn.model.api.Vector` - Object: Interface framework-specific data structures. - Usage: Wrap and operate on model weights, gradients, updates... @@ -54,7 +60,34 @@ new custom concrete implementations inheriting the abstraction. - `declearn.model.torch.TorchVector` - Extend: use `declearn.model.api.register_vector_type` -### `OptiModule` +### Federated Optimization + +You may learn more about our (non-abstract) `Optimizer` API by reading our +[Optimizer guide](./optimizer.md). + +#### `Aggregator` +- Import: `declearn.aggregator.Aggregator` +- Object: Define model updates aggregation algorithms. +- Usage: Post-process client updates; finalize aggregated global ones. +- Examples: + - `declearn.aggregator.AveragingAggregator` + - `declearn.aggregator.GradientMaskedAveraging` +- Extend: + - Simply inherit from `Aggregator` (registration is automated). + - To avoid it, use `class MyAggregator(Aggregator, register=False)`. + +#### `ModelUpdates` +- Import: `declearn.aggregator.ModelUpdates` +- Object: Define exchanged model updates data and their aggregation. +- Usage: Share and aggregate client's updates for a given `Aggregator`. +- Examples: + - Each `Aggregator` has its own dedicated/supported `ModelUpdates` type(s). +- Extend: + - Simply inherit from `ModelUpdates` (registration is automated). + - Define a `name` class attribute and decorate as a `dataclass`. + - To avoid it, use `class MyModelUpdates(ModelUpdates, register=False)`. + +#### `OptiModule` - Import: `declearn.optimizer.modules.OptiModule` - Object: Define optimization algorithm bricks. - Usage: Plug into a `declearn.optimizer.Optimizer`. @@ -67,19 +100,33 @@ new custom concrete implementations inheriting the abstraction. - Simply inherit from `OptiModule` (registration is automated). - To avoid it, use `class MyModule(OptiModule, register=False)`. -### `Regularizer` -- Import: `declearn.optimizer.modules.Regularizer` +#### `Regularizer` +- Import: `declearn.optimizer.regularizers.Regularizer` - Object: Define loss-regularization terms as gradients modifiers. - Usage: Plug into a `declearn.optimizer.Optimizer`. - Examples: - - `declearn.optimizer.regularizer.FedProxRegularizer` - - `declearn.optimizer.regularizer.LassoRegularizer` - - `declearn.optimizer.regularizer.RidgeRegularizer` + - `declearn.optimizer.regularizers.FedProxRegularizer` + - `declearn.optimizer.regularizers.LassoRegularizer` + - `declearn.optimizer.regularizers.RidgeRegularizer` - Extend: - Simply inherit from `Regularizer` (registration is automated). - To avoid it, use `class MyRegularizer(Regularizer, register=False)`. -### `Metric` +#### `AuxVar` +- Import: `declearn.optimizer.modules.AuxVar` +- Object: Define exchanged data between a pair of `OptiModules` across the + clients/server boundary, and their aggregation. +- Usage: Share information from server to clients and reciprocally. +- Examples: + - `declearn.optimizer.modules.ScaffoldAuxVar` +- Extend: + - Simply inherit from `AuxVar` (registration is automated). + - Define a `name` class attribute and decorate as a `dataclass`. + - To avoid it, use `class MyAuxVar(AuxVar, register=False)`. + +### Evaluation Metrics + +#### `Metric` - Import: `declearn.metrics.Metric` - Object: Define evaluation metrics to compute iteratively and federatively. - Usage: Compute local and federated metrics based on local data streams. @@ -89,9 +136,22 @@ new custom concrete implementations inheriting the abstraction. - `declearn.metric.MuticlassAccuracyPrecisionRecall` - Extend: - Simply inherit from `Metric` (registration is automated). - - To avoid it, use `class MyMetric(Metric, register=False)` + - To avoid it, use `class MyMetric(Metric, register=False)`. + +#### `MetricState` +- Import: `declearn.metrics.MetricState` +- Object: Define exchanged data to compute a `Metric` and their aggregation. +- Usage: Share locally-computed metrics for their aggregation into global ones. +- Examples: + - Each `Metric` has its own dedicated/supported `MetricState` type(s). +- Extend: + - Simply inherit from `MetricState` (registration is automated). + - Define a `name` class attribute and decorate as a `dataclass`. + - To avoid it, use `class MyMetricState(MetricState, register=False)`. -### `NetworkClient` +### Network communication + +#### `NetworkClient` - Import: `declearn.communication.api.NetworkClient` - Object: Instantiate a network communication client endpoint. - Usage: Register for training, send and receive messages. @@ -102,7 +162,7 @@ new custom concrete implementations inheriting the abstraction. - Simply inherit from `NetworkClient` (registration is automated). - To avoid it, use `class MyClient(NetworkClient, register=False)`. -### `NetworkServer` +#### `NetworkServer` - Import: `declearn.communication.api.NetworkServer` - Object: Instantiate a network communication server endpoint. - Usage: Receive clients' requests, send and receive messages. @@ -113,13 +173,30 @@ new custom concrete implementations inheriting the abstraction. - Simply inherit from `NetworkServer` (registration is automated). - To avoid it, use `class MyServer(NetworkServer, register=False)`. -### `Dataset` +#### `Message` +- Import: `declearn.messaging.Message` +- Object: Define serializable/parsable message types and their data. +- Usage: Exchanged via communication endpoints to transmit data and + trigger behaviors based on type analysis. +- Examples: + - `declearn.messages.TrainRequest` + - `declearn.messages.TrainReply` + - `declearn.messages.Error` +- Extend: + - Simply inherit from `Message` (registration is automated). + - To avoid it, use `class MyMessage(Message, register=False)`. + +### Dataset + +#### `Dataset` - Import: `declearn.dataset.Dataset` - Object: Interface data sources agnostic to their format. - Usage: Yield (inputs, labels, weights) data batches, expose metadata. - Examples: - `declearn.dataset.InMemoryDataset` -- Extend: use `declearn.utils.register_type(group="Dataset")` + - `declearn.dataset.tensorflow.TensorflowDataset` + - `declearn.dataset.torch.TorchDataset` +- Extend: use `declearn.utils.register_type(group="Dataset")`. ## Full API Reference